From e3c9a420d2382f7b634ca3bca1974eeda1d55ccd Mon Sep 17 00:00:00 2001 From: Novout Date: Sun, 23 Apr 2023 19:49:54 -0300 Subject: [PATCH] feat(liveshare): improve icons and ctx --- .../main/render/EditorBaseRenderBar.vue | 2 +- .../bar/EditorBaseRenderBarLiveshare.vue | 27 ++-- .../presence/EditorProjectPresenceCreate.vue | 33 ++--- .../EditorProjectPresenceInformation.vue | 54 ++++++++ .../EditorProjectPresenceInformationType.vue | 16 +++ .../presence/EditorProjectPresenceKey.vue | 31 +++++ .../better-write-app/src/store/liveshare.ts | 2 + .../src/use/storage/supabase.ts | 7 +- packages/better-write-app/vite.config.ts | 9 +- .../src/en-US/editor.ts | 25 ++++ .../src/pt-BR/editor.ts | 13 ++ .../better-write-plugin-liveshare/src/room.ts | 125 ++++++++++++------ .../css/themes/betterwrite-custom.css | 8 +- packages/better-write-types/src/liveshare.ts | 3 + 14 files changed, 276 insertions(+), 79 deletions(-) create mode 100644 packages/better-write-app/src/components/page/editor/project/presence/EditorProjectPresenceInformation.vue create mode 100644 packages/better-write-app/src/components/page/editor/project/presence/EditorProjectPresenceInformationType.vue create mode 100644 packages/better-write-app/src/components/page/editor/project/presence/EditorProjectPresenceKey.vue diff --git a/packages/better-write-app/src/components/page/editor/main/render/EditorBaseRenderBar.vue b/packages/better-write-app/src/components/page/editor/main/render/EditorBaseRenderBar.vue index d326729af..20fbf2712 100644 --- a/packages/better-write-app/src/components/page/editor/main/render/EditorBaseRenderBar.vue +++ b/packages/better-write-app/src/components/page/editor/main/render/EditorBaseRenderBar.vue @@ -11,7 +11,7 @@ -
+
diff --git a/packages/better-write-app/src/components/page/editor/main/render/bar/EditorBaseRenderBarLiveshare.vue b/packages/better-write-app/src/components/page/editor/main/render/bar/EditorBaseRenderBarLiveshare.vue index 6d6c8081b..a7a0cdf64 100644 --- a/packages/better-write-app/src/components/page/editor/main/render/bar/EditorBaseRenderBarLiveshare.vue +++ b/packages/better-write-app/src/components/page/editor/main/render/bar/EditorBaseRenderBarLiveshare.vue @@ -1,19 +1,28 @@ diff --git a/packages/better-write-app/src/components/page/editor/project/presence/EditorProjectPresenceCreate.vue b/packages/better-write-app/src/components/page/editor/project/presence/EditorProjectPresenceCreate.vue index 73ad824a9..9c1aca426 100644 --- a/packages/better-write-app/src/components/page/editor/project/presence/EditorProjectPresenceCreate.vue +++ b/packages/better-write-app/src/components/page/editor/project/presence/EditorProjectPresenceCreate.vue @@ -7,19 +7,14 @@ >

{{ t('editor.presence.create.description') }}

-
- - +
+ +

{{ t('editor.presence.create.new') }}

- -
-

{{ key }}

- -
+ +

{{ t('editor.presence.create.enterInput') }}

@@ -32,11 +27,10 @@ diff --git a/packages/better-write-app/src/components/page/editor/project/presence/EditorProjectPresenceInformation.vue b/packages/better-write-app/src/components/page/editor/project/presence/EditorProjectPresenceInformation.vue new file mode 100644 index 000000000..6ca199e00 --- /dev/null +++ b/packages/better-write-app/src/components/page/editor/project/presence/EditorProjectPresenceInformation.vue @@ -0,0 +1,54 @@ + + + \ No newline at end of file diff --git a/packages/better-write-app/src/components/page/editor/project/presence/EditorProjectPresenceInformationType.vue b/packages/better-write-app/src/components/page/editor/project/presence/EditorProjectPresenceInformationType.vue new file mode 100644 index 000000000..bdf0d56bb --- /dev/null +++ b/packages/better-write-app/src/components/page/editor/project/presence/EditorProjectPresenceInformationType.vue @@ -0,0 +1,16 @@ + + + \ No newline at end of file diff --git a/packages/better-write-app/src/components/page/editor/project/presence/EditorProjectPresenceKey.vue b/packages/better-write-app/src/components/page/editor/project/presence/EditorProjectPresenceKey.vue new file mode 100644 index 000000000..f074d12ed --- /dev/null +++ b/packages/better-write-app/src/components/page/editor/project/presence/EditorProjectPresenceKey.vue @@ -0,0 +1,31 @@ + + + \ No newline at end of file diff --git a/packages/better-write-app/src/store/liveshare.ts b/packages/better-write-app/src/store/liveshare.ts index bb4dca3d5..00f1895fa 100644 --- a/packages/better-write-app/src/store/liveshare.ts +++ b/packages/better-write-app/src/store/liveshare.ts @@ -7,6 +7,8 @@ export const useLiveshareStore = defineStore('liveshare', { presence: {}, presenceLimit: 5, ownerKey: undefined, + roomKey: undefined, + lastUpdatedColor: undefined, } }, actions: { diff --git a/packages/better-write-app/src/use/storage/supabase.ts b/packages/better-write-app/src/use/storage/supabase.ts index 30cf02792..f5cc7abd0 100644 --- a/packages/better-write-app/src/use/storage/supabase.ts +++ b/packages/better-write-app/src/use/storage/supabase.ts @@ -25,7 +25,12 @@ const supabaseUrl = import.meta.env.VITE_SUPABASE_URL const supabaseAnonKey = import.meta.env.VITE_SUPABASE_ANON_KEY export const s = createClient(supabaseUrl, supabaseAnonKey, { - auth: { storageKey: '__BW__' } + auth: { storageKey: '__BW__' }, + realtime: { + params: { + eventsPerSecond: 10 + } + } }) export const getSupabaseUser = async () => { diff --git a/packages/better-write-app/vite.config.ts b/packages/better-write-app/vite.config.ts index e67e28f74..6497ab77a 100644 --- a/packages/better-write-app/vite.config.ts +++ b/packages/better-write-app/vite.config.ts @@ -53,7 +53,7 @@ export default ({ mode }) => { }), windiCSS(), CSSFontaine.vite({ - fallbacks: ['Raleway', 'Poppins', 'BlinkMacSystemFont', 'Segoe UI', 'Helvetica Neue', 'Arial', 'Noto Sans'], + fallbacks: ['BlinkMacSystemFont', 'Segoe UI', 'Helvetica Neue', 'Arial', 'Noto Sans'], resolvePath: id => new URL('.' + id, import.meta.url), }), viteSitemap({ @@ -76,9 +76,8 @@ export default ({ mode }) => { viteAutoImport({ dts: './imports.d.ts', include: [ - /\.[tj]sx?$/, // .ts, .tsx, .js, .jsx - /\.vue$/, /\.vue\?vue/, // .vue - /\.md$/ // .md + /\.[tj]sx?$/, + /\.vue$/, /\.vue\?vue/ ], imports: [ 'vue', @@ -88,7 +87,7 @@ export default ({ mode }) => { vitePWA({ base: '/', registerType: 'prompt', - includeAssets: fg.sync('**/*.{png,svg,json,ico,txt,xml,ttf}', { cwd: resolve(__dirname, 'public') }), + includeAssets: fg.sync('**/*.{png,svg,json,mp3,ico,txt,xml,ttf}', { cwd: resolve(__dirname, 'public') }), manifest: { name: 'Better Write', short_name: 'Better Write', diff --git a/packages/better-write-languages/src/en-US/editor.ts b/packages/better-write-languages/src/en-US/editor.ts index 305c92a21..f837e652b 100644 --- a/packages/better-write-languages/src/en-US/editor.ts +++ b/packages/better-write-languages/src/en-US/editor.ts @@ -840,4 +840,29 @@ export default { }, }, }, + presence: { + type: { + owner: 'Owner', + visit: 'Visitant', + }, + bar: { + liveshare: 'Sharing...', + }, + create: { + title: 'Live Share', + description: + 'Share your project with others in real time to build an experience together!', + button: 'Create Room', + or: 'Or', + new: 'Create Room:', + enterInput: 'Enter Room:', + enterPlaceholder: 'vCAQe6FD3D...', + }, + info: { + enter: 'Enter', + create: 'Create', + title: 'Share Room', + leave: 'Leave Room', + }, + }, } diff --git a/packages/better-write-languages/src/pt-BR/editor.ts b/packages/better-write-languages/src/pt-BR/editor.ts index 2f0167a20..b9b5fdde2 100644 --- a/packages/better-write-languages/src/pt-BR/editor.ts +++ b/packages/better-write-languages/src/pt-BR/editor.ts @@ -847,6 +847,13 @@ export default { }, }, presence: { + type: { + owner: 'Dono', + visit: 'Visitante', + }, + bar: { + liveshare: 'Compartilhando...', + }, create: { title: 'Compartilhamento', description: @@ -857,5 +864,11 @@ export default { enterInput: 'Entre em uma sala:', enterPlaceholder: 'vCAQe6FD3D...', }, + info: { + enter: 'Entrar', + create: 'Criar', + title: 'Sala Compartilhada', + leave: 'Sair da Sala', + }, }, } diff --git a/packages/better-write-plugin-liveshare/src/room.ts b/packages/better-write-plugin-liveshare/src/room.ts index 3c0e9c7bc..eab493635 100644 --- a/packages/better-write-plugin-liveshare/src/room.ts +++ b/packages/better-write-plugin-liveshare/src/room.ts @@ -1,10 +1,12 @@ import { On } from 'better-write-plugin-core' import type { + ContextState, LivesharePresenceItem, + Maybe, PluginTypes, ProjectObject, } from 'better-write-types' -import type { RealtimeChannel } from '@supabase/supabase-js' +import type { RealtimeChannel, User } from '@supabase/supabase-js' import { nanoid } from 'nanoid' import { computed } from 'vue-demi' @@ -13,70 +15,98 @@ export const RoomSet = ( stores: PluginTypes.PluginStores, hooks: PluginTypes.PluginHooks ) => { - const setCTX = (ctx: ProjectObject) => { + const setCTX = (object: ProjectObject, ctx: ContextState) => { // TODO: better method for track changes - stores.PROJECT.$state = ctx.project - stores.EDITOR.$state = ctx.editor - stores.PDF.$state = ctx.pdf - stores.DOCX.$state = ctx.docx + stores.CONTEXT.$state = ctx + stores.PROJECT.$state = object.project + stores.EDITOR.$state = object.editor + stores.PDF.$state = object.pdf + stores.DOCX.$state = object.docx } const getCTX = (): { type: string event: string - payload: { ctx: ProjectObject } + payload: { object: ProjectObject; ctx: ContextState; user: Maybe } } => ({ type: 'broadcast', event: 'ctx', - payload: { ctx: hooks.storage.getProjectObject() }, + payload: { + object: hooks.storage.getProjectObject(), + ctx: stores.CONTEXT.$state, + user: stores.AUTH.account.user, + }, }) + const setWatcher = (channel: RealtimeChannel) => { + hooks.vueuse.core.watchDebounced( + [ + computed(() => stores.PROJECT.$state), + computed(() => stores.CONTEXT.$state), + ], + () => { + const ctx = getCTX() + + channel.send(ctx) + }, + { debounce: 1000, maxWait: 2000, immediate: true, deep: true } + ) + } + const setRoom = ( channel: RealtimeChannel, type: 'owner' | 'visit' ): RealtimeChannel => { channel .on('presence', { event: 'join' }, ({ key, newPresences }) => { - // TODO: @vueuse/sound in enter new user + stores.LIVESHARE.add({ + [key]: newPresences, + }) if (type === 'owner') stores.LIVESHARE.ownerKey = key }) .on('presence', { event: 'leave' }, async ({ key, leftPresences }) => { - // TODO: @vueuse/sound in leave new user + try { + delete stores.LIVESHARE.presence[key] + } catch (e) {} if (key === stores.LIVESHARE.ownerKey) { await channel.unsubscribe().catch(() => {}) stores.LIVESHARE.$reset() - - // TODO: check if project is destroyed or not } }) .on('presence', { event: 'sync' }, () => { const state = channel.presenceState() - if (state) stores.LIVESHARE.presence = state + stores.LIVESHARE.presence = state }) - .on('broadcast', { event: 'ctx' }, (payload) => { + .on('broadcast', { event: 'ctx' }, ({ payload }) => { if (type === 'owner') return - setCTX(payload.ctx) + setCTX(payload.object, payload.ctx) + }) + .subscribe(async (status) => { + if (status === 'SUBSCRIBED') { + // TODO: use's safe random color or predefined arr colors + const hexColor = hooks.utils.text().randomColor() + + await channel.track({ + id: stores.AUTH.account.user?.email ?? stores.AUTH.account.user?.id, + type, + avatar_url: + stores.AUTH.account.user?.user_metadata?.avatar_url ?? undefined, + online_at: new Date().toISOString(), + color: hexColor, + }) + + if (type === 'owner') { + channel.send(getCTX()) + stores.LIVESHARE.lastUpdatedColor = hexColor + } + } }) - - channel.subscribe(async (status) => { - if (status === 'SUBSCRIBED') { - await channel.track({ - id: stores.AUTH.account.user?.email ?? stores.AUTH.account.user?.id, - avatar_url: - stores.AUTH.account.user?.user_metadata?.avatar_url ?? undefined, - online_at: new Date().toISOString(), - color: hooks.utils.text().randomColor(), // TODO: use's safe random color or predefined arr colors - }) - - if (type === 'owner') channel.send(getCTX()) - } - }) return channel } @@ -88,25 +118,28 @@ export const RoomSet = ( const channel = hooks.supabase.channel(id) setRoom(channel, 'owner') + setWatcher(channel) - hooks.vueuse.core.watchDebounced( - computed(() => stores.PROJECT.$state), - () => { - channel.send(getCTX()) - }, - { debounce: 1000, maxWait: 2000, immediate: true, deep: false } - ) + stores.LIVESHARE.roomKey = id emitter.emit('plugin-presence-room-create-key', id) + + hooks.toast.success(hooks.i18n.t('toast.generics.successCreated')) }, () => {}, ]) On.externals().PluginPresenceRoomJoin(emitter, [ async (id: string) => { + if (stores.LIVESHARE.roomKey) return + const channel = hooks.supabase.channel(id) - if (!channel) return + if (!channel) { + hooks.toast.error(hooks.i18n.t('toast.generics.error')) + + return + } if ( Object.entries(channel.presence.state).length >= @@ -118,6 +151,24 @@ export const RoomSet = ( } setRoom(channel, 'visit') + + stores.LIVESHARE.roomKey = id + stores.ABSOLUTE.modal.presence.info = false + stores.ABSOLUTE.modal.presence.createOrJoin = false + + hooks.toast.success(hooks.i18n.t('toast.generics.successCreated')) + }, + () => {}, + ]) + + On.externals().PluginPresenceRoomLeave(emitter, [ + async (id: string) => { + const channel = hooks.supabase.channel(id) + + await channel.unsubscribe().catch(() => {}) + + stores.ABSOLUTE.modal.presence.info = false + stores.ABSOLUTE.modal.presence.createOrJoin = false }, () => {}, ]) diff --git a/packages/better-write-plugin-theme/css/themes/betterwrite-custom.css b/packages/better-write-plugin-theme/css/themes/betterwrite-custom.css index e2e69e1a4..9e3f806f2 100644 --- a/packages/better-write-plugin-theme/css/themes/betterwrite-custom.css +++ b/packages/better-write-plugin-theme/css/themes/betterwrite-custom.css @@ -3,10 +3,10 @@ --theme-transparent: transparent; --theme-black: #000000; --theme-white: #ffffff; - --theme-background-1: rgba(0, 0, 0, 0.75); - --theme-background-2: rgba(0, 0, 0, 0.75); - --theme-background-3: rgba(0, 0, 0, 0.75); - --theme-background-4: rgba(0, 0, 0, 0.75); + --theme-background-1: rgba(0, 0, 0, 0.5); + --theme-background-2: rgba(0, 0, 0, 0.5); + --theme-background-3: rgba(0, 0, 0, 0.5); + --theme-background-4: rgba(0, 0, 0, 0.5); --theme-background-opacity-1: rgba(0, 0, 0, 0.15); --theme-background-absolute-1: rgba(0, 0, 0, 0.75); --theme-border-1: rgba(0, 0, 0, 0.75); diff --git a/packages/better-write-types/src/liveshare.ts b/packages/better-write-types/src/liveshare.ts index d89978e14..eee77e95b 100644 --- a/packages/better-write-types/src/liveshare.ts +++ b/packages/better-write-types/src/liveshare.ts @@ -1,5 +1,6 @@ export interface LivesharePresenceItem { id: string + type: 'owner' | 'visit' avatar_url?: string online_at: string color: string @@ -10,6 +11,8 @@ export interface LiveshareState { presence: { [x: string]: LivesharePresenceItem[] } + roomKey?: string presenceLimit: number ownerKey?: string + lastUpdatedColor?: string }