From 38a53b95ec8c7a195621be1f0ea674f823550fce Mon Sep 17 00:00:00 2001 From: sim1222 Date: Sun, 17 Jul 2022 06:49:25 +0900 Subject: [PATCH] feat: restore old deck ui --- locales/ja-JP.yml | 1 + locales/ja-NY.yml | 2 + package.json | 2 +- packages/client/src/init.ts | 1 + packages/client/src/navbar.ts | 7 + packages/client/src/ui/_common_old/common.vue | 123 +++++ .../src/ui/_common_old/sidebar-for-mobile.vue | 225 ++++++++ .../client/src/ui/_common_old/sidebar.vue | 497 ++++++++++++++++++ .../src/ui/_common_old/stream-indicator.vue | 60 +++ .../client/src/ui/_common_old/sw-inject.ts | 35 ++ packages/client/src/ui/_common_old/upload.vue | 128 +++++ packages/client/src/ui/deckold.vue | 305 +++++++++++ .../client/src/ui/deckold/antenna-column.vue | 63 +++ .../client/src/ui/deckold/column-core.vue | 44 ++ packages/client/src/ui/deckold/column.vue | 393 ++++++++++++++ packages/client/src/ui/deckold/deck-store.ts | 317 +++++++++++ .../client/src/ui/deckold/direct-column.vue | 31 ++ .../client/src/ui/deckold/list-column.vue | 66 +++ .../client/src/ui/deckold/main-column.vue | 68 +++ .../client/src/ui/deckold/mentions-column.vue | 28 + .../src/ui/deckold/notifications-column.vue | 38 ++ packages/client/src/ui/deckold/tl-column.vue | 129 +++++ .../client/src/ui/deckold/widgets-column.vue | 63 +++ 23 files changed, 2625 insertions(+), 1 deletion(-) create mode 100644 packages/client/src/ui/_common_old/common.vue create mode 100644 packages/client/src/ui/_common_old/sidebar-for-mobile.vue create mode 100644 packages/client/src/ui/_common_old/sidebar.vue create mode 100644 packages/client/src/ui/_common_old/stream-indicator.vue create mode 100644 packages/client/src/ui/_common_old/sw-inject.ts create mode 100644 packages/client/src/ui/_common_old/upload.vue create mode 100644 packages/client/src/ui/deckold.vue create mode 100644 packages/client/src/ui/deckold/antenna-column.vue create mode 100644 packages/client/src/ui/deckold/column-core.vue create mode 100644 packages/client/src/ui/deckold/column.vue create mode 100644 packages/client/src/ui/deckold/deck-store.ts create mode 100644 packages/client/src/ui/deckold/direct-column.vue create mode 100644 packages/client/src/ui/deckold/list-column.vue create mode 100644 packages/client/src/ui/deckold/main-column.vue create mode 100644 packages/client/src/ui/deckold/mentions-column.vue create mode 100644 packages/client/src/ui/deckold/notifications-column.vue create mode 100644 packages/client/src/ui/deckold/tl-column.vue create mode 100644 packages/client/src/ui/deckold/widgets-column.vue diff --git a/locales/ja-JP.yml b/locales/ja-JP.yml index d432f8a0e..a0e1de2b9 100644 --- a/locales/ja-JP.yml +++ b/locales/ja-JP.yml @@ -891,6 +891,7 @@ activeEmailValidationDescription: "ユーザーのメールアドレスのバリ navbar: "ナビゲーションバー" shuffle: "シャッフル" account: "アカウント" +deckOld: "旧デッキ" _sensitiveMediaDetection: description: "機械学習を使って自動でセンシティブなメディアを検出し、モデレーションに役立てることができます。サーバーの負荷が少し増えます。" diff --git a/locales/ja-NY.yml b/locales/ja-NY.yml index fa1762624..cd653efc3 100644 --- a/locales/ja-NY.yml +++ b/locales/ja-NY.yml @@ -835,6 +835,8 @@ emojiStretch: "自動で伸縮しない" emojiGenerate: "生成" emojiColor: "カラーコード" emojiApproval: "絵文字を登録" +deckOld: "旧デッキ" + _emailUnavailable: used: "既に使用されているにゃ" diff --git a/package.json b/package.json index 464b02629..0ef90a226 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "misskey", - "version": "12.116.0-simkey-v1", + "version": "12.116.0-simkey-v2", "codename": "indigo", "repository": { "type": "git", diff --git a/packages/client/src/init.ts b/packages/client/src/init.ts index e39b95534..529b8d829 100644 --- a/packages/client/src/init.ts +++ b/packages/client/src/init.ts @@ -172,6 +172,7 @@ import { getAccountFromId } from '@/scripts/get-account-from-id'; window.location.search === '?zen' ? defineAsyncComponent(() => import('@/ui/zen.vue')) : !$i ? defineAsyncComponent(() => import('@/ui/visitor.vue')) : ui === 'deck' ? defineAsyncComponent(() => import('@/ui/deck.vue')) : + ui === 'deckold' ? defineAsyncComponent(() => import('@/ui/deckold.vue')) : ui === 'classic' ? defineAsyncComponent(() => import('@/ui/classic.vue')) : defineAsyncComponent(() => import('@/ui/universal.vue')), ); diff --git a/packages/client/src/navbar.ts b/packages/client/src/navbar.ts index 03e00b1c1..6f5855961 100644 --- a/packages/client/src/navbar.ts +++ b/packages/client/src/navbar.ts @@ -115,6 +115,13 @@ export const navbarItemDef = reactive({ localStorage.setItem('ui', 'deck'); unisonReload(); }, + }, { + text: i18n.ts.deckOld, + active: ui === 'deckold', + action: () => { + localStorage.setItem('ui', 'deckold'); + unisonReload(); + }, }, { text: i18n.ts.classic, active: ui === 'classic', diff --git a/packages/client/src/ui/_common_old/common.vue b/packages/client/src/ui/_common_old/common.vue new file mode 100644 index 000000000..e8641d3ad --- /dev/null +++ b/packages/client/src/ui/_common_old/common.vue @@ -0,0 +1,123 @@ + + + + + diff --git a/packages/client/src/ui/_common_old/sidebar-for-mobile.vue b/packages/client/src/ui/_common_old/sidebar-for-mobile.vue new file mode 100644 index 000000000..d75a8f456 --- /dev/null +++ b/packages/client/src/ui/_common_old/sidebar-for-mobile.vue @@ -0,0 +1,225 @@ + + + + + diff --git a/packages/client/src/ui/_common_old/sidebar.vue b/packages/client/src/ui/_common_old/sidebar.vue new file mode 100644 index 000000000..e155098bb --- /dev/null +++ b/packages/client/src/ui/_common_old/sidebar.vue @@ -0,0 +1,497 @@ + + + + + diff --git a/packages/client/src/ui/_common_old/stream-indicator.vue b/packages/client/src/ui/_common_old/stream-indicator.vue new file mode 100644 index 000000000..5e811e1b8 --- /dev/null +++ b/packages/client/src/ui/_common_old/stream-indicator.vue @@ -0,0 +1,60 @@ + + + + + diff --git a/packages/client/src/ui/_common_old/sw-inject.ts b/packages/client/src/ui/_common_old/sw-inject.ts new file mode 100644 index 000000000..de612438b --- /dev/null +++ b/packages/client/src/ui/_common_old/sw-inject.ts @@ -0,0 +1,35 @@ +import { inject } from 'vue'; +import { post } from '@/os'; +import { $i, login } from '@/account'; +import { defaultStore } from '@/store'; +import { getAccountFromId } from '@/scripts/get-account-from-id'; +import { mainRouter } from '@/router'; + +export function swInject() { + navigator.serviceWorker.addEventListener('message', ev => { + if (_DEV_) { + console.log('sw msg', ev.data); + } + + if (ev.data.type !== 'order') return; + + if (ev.data.loginId !== $i?.id) { + return getAccountFromId(ev.data.loginId).then(account => { + if (!account) return; + return login(account.token, ev.data.url); + }); + } + + switch (ev.data.order) { + case 'post': + return post(ev.data.options); + case 'push': + if (mainRouter.currentRoute.value.path === ev.data.url) { + return window.scroll({ top: 0, behavior: 'smooth' }); + } + return mainRouter.push(ev.data.url); + default: + return; + } + }); +} diff --git a/packages/client/src/ui/_common_old/upload.vue b/packages/client/src/ui/_common_old/upload.vue new file mode 100644 index 000000000..3f73daf26 --- /dev/null +++ b/packages/client/src/ui/_common_old/upload.vue @@ -0,0 +1,128 @@ + + + + + diff --git a/packages/client/src/ui/deckold.vue b/packages/client/src/ui/deckold.vue new file mode 100644 index 000000000..eefb61213 --- /dev/null +++ b/packages/client/src/ui/deckold.vue @@ -0,0 +1,305 @@ + + + + + diff --git a/packages/client/src/ui/deckold/antenna-column.vue b/packages/client/src/ui/deckold/antenna-column.vue new file mode 100644 index 000000000..f12f5c6b2 --- /dev/null +++ b/packages/client/src/ui/deckold/antenna-column.vue @@ -0,0 +1,63 @@ + + + + + diff --git a/packages/client/src/ui/deckold/column-core.vue b/packages/client/src/ui/deckold/column-core.vue new file mode 100644 index 000000000..2667b6d74 --- /dev/null +++ b/packages/client/src/ui/deckold/column-core.vue @@ -0,0 +1,44 @@ + + + diff --git a/packages/client/src/ui/deckold/column.vue b/packages/client/src/ui/deckold/column.vue new file mode 100644 index 000000000..126164327 --- /dev/null +++ b/packages/client/src/ui/deckold/column.vue @@ -0,0 +1,393 @@ + + + + + + diff --git a/packages/client/src/ui/deckold/deck-store.ts b/packages/client/src/ui/deckold/deck-store.ts new file mode 100644 index 000000000..290913a52 --- /dev/null +++ b/packages/client/src/ui/deckold/deck-store.ts @@ -0,0 +1,317 @@ +import { throttle } from 'throttle-debounce'; +import { markRaw } from 'vue'; +import { notificationTypes } from 'misskey-js'; +import { Storage } from '../../pizzax'; +import { i18n } from '@/i18n'; +import { api } from '@/os'; + +type ColumnWidget = { + name: string; + id: string; + data: Record; +}; + +export type Column = { + id: string; + type: 'main' | 'widgets' | 'notifications' | 'tl' | 'antenna' | 'list' | 'mentions' | 'direct'; + name: string | null; + width: number; + widgets?: ColumnWidget[]; + active?: boolean; + flexible?: boolean; + antennaId?: string; + listId?: string; + includingTypes?: typeof notificationTypes[number][]; + tl?: 'home' | 'local' | 'social' | 'global'; +}; + +function copy(x: T): T { + return JSON.parse(JSON.stringify(x)); +} + +export const deckStore = markRaw(new Storage('deck', { + profile: { + where: 'deviceAccount', + default: 'default', + }, + columns: { + where: 'deviceAccount', + default: [] as Column[], + }, + layout: { + where: 'deviceAccount', + default: [] as Column['id'][][], + }, + columnAlign: { + where: 'deviceAccount', + default: 'left' as 'left' | 'right' | 'center', + }, + alwaysShowMainColumn: { + where: 'deviceAccount', + default: true, + }, + navWindow: { + where: 'deviceAccount', + default: true, + }, + columnMargin: { + where: 'deviceAccount', + default: 12, + }, + columnHeaderHeight: { + where: 'deviceAccount', + default: 42, + }, +})); + +export const loadDeck = async () => { + let deck; + + try { + deck = await api('i/registry/get', { + scope: ['client', 'deck', 'profiles'], + key: deckStore.state.profile, + }); + } catch (err) { + if (err.code === 'NO_SUCH_KEY') { + // 後方互換性のため + if (deckStore.state.profile === 'default') { + saveDeck(); + return; + } + + deckStore.set('columns', [{ + id: 'a', + type: 'main', + name: i18n.ts._deck._columns.main, + width: 350, + }, { + id: 'b', + type: 'notifications', + name: i18n.ts._deck._columns.notifications, + width: 330, + }]); + deckStore.set('layout', [['a'], ['b']]); + return; + } + throw err; + } + + deckStore.set('columns', deck.columns); + deckStore.set('layout', deck.layout); +}; + +// TODO: deckがloadされていない状態でsaveすると意図せず上書きが発生するので対策する +export const saveDeck = throttle(1000, () => { + api('i/registry/set', { + scope: ['client', 'deck', 'profiles'], + key: deckStore.state.profile, + value: { + columns: deckStore.reactiveState.columns.value, + layout: deckStore.reactiveState.layout.value, + }, + }); +}); + +export async function getProfiles(): Promise { + return await api('i/registry/keys', { + scope: ['client', 'deck', 'profiles'], + }); +} + +export async function deleteProfile(key: string): Promise { + return await api('i/registry/remove', { + scope: ['client', 'deck', 'profiles'], + key: key, + }); +} + +export function addColumn(column: Column) { + if (column.name === undefined) column.name = null; + deckStore.push('columns', column); + deckStore.push('layout', [column.id]); + saveDeck(); +} + +export function removeColumn(id: Column['id']) { + deckStore.set('columns', deckStore.state.columns.filter(c => c.id !== id)); + deckStore.set('layout', deckStore.state.layout + .map(ids => ids.filter(_id => _id !== id)) + .filter(ids => ids.length > 0)); + saveDeck(); +} + +export function swapColumn(a: Column['id'], b: Column['id']) { + const aX = deckStore.state.layout.findIndex(ids => ids.indexOf(a) !== -1); + const aY = deckStore.state.layout[aX].findIndex(id => id === a); + const bX = deckStore.state.layout.findIndex(ids => ids.indexOf(b) !== -1); + const bY = deckStore.state.layout[bX].findIndex(id => id === b); + const layout = copy(deckStore.state.layout); + layout[aX][aY] = b; + layout[bX][bY] = a; + deckStore.set('layout', layout); + saveDeck(); +} + +export function swapLeftColumn(id: Column['id']) { + const layout = copy(deckStore.state.layout); + deckStore.state.layout.some((ids, i) => { + if (ids.includes(id)) { + const left = deckStore.state.layout[i - 1]; + if (left) { + layout[i - 1] = deckStore.state.layout[i]; + layout[i] = left; + deckStore.set('layout', layout); + } + return true; + } + }); + saveDeck(); +} + +export function swapRightColumn(id: Column['id']) { + const layout = copy(deckStore.state.layout); + deckStore.state.layout.some((ids, i) => { + if (ids.includes(id)) { + const right = deckStore.state.layout[i + 1]; + if (right) { + layout[i + 1] = deckStore.state.layout[i]; + layout[i] = right; + deckStore.set('layout', layout); + } + return true; + } + }); + saveDeck(); +} + +export function swapUpColumn(id: Column['id']) { + const layout = copy(deckStore.state.layout); + const idsIndex = deckStore.state.layout.findIndex(ids => ids.includes(id)); + const ids = copy(deckStore.state.layout[idsIndex]); + ids.some((x, i) => { + if (x === id) { + const up = ids[i - 1]; + if (up) { + ids[i - 1] = id; + ids[i] = up; + + layout[idsIndex] = ids; + deckStore.set('layout', layout); + } + return true; + } + }); + saveDeck(); +} + +export function swapDownColumn(id: Column['id']) { + const layout = copy(deckStore.state.layout); + const idsIndex = deckStore.state.layout.findIndex(ids => ids.includes(id)); + const ids = copy(deckStore.state.layout[idsIndex]); + ids.some((x, i) => { + if (x === id) { + const down = ids[i + 1]; + if (down) { + ids[i + 1] = id; + ids[i] = down; + + layout[idsIndex] = ids; + deckStore.set('layout', layout); + } + return true; + } + }); + saveDeck(); +} + +export function stackLeftColumn(id: Column['id']) { + let layout = copy(deckStore.state.layout); + const i = deckStore.state.layout.findIndex(ids => ids.includes(id)); + layout = layout.map(ids => ids.filter(_id => _id !== id)); + layout[i - 1].push(id); + layout = layout.filter(ids => ids.length > 0); + deckStore.set('layout', layout); + saveDeck(); +} + +export function popRightColumn(id: Column['id']) { + let layout = copy(deckStore.state.layout); + const i = deckStore.state.layout.findIndex(ids => ids.includes(id)); + const affected = layout[i]; + layout = layout.map(ids => ids.filter(_id => _id !== id)); + layout.splice(i + 1, 0, [id]); + layout = layout.filter(ids => ids.length > 0); + deckStore.set('layout', layout); + + const columns = copy(deckStore.state.columns); + for (const column of columns) { + if (affected.includes(column.id)) { + column.active = true; + } + } + deckStore.set('columns', columns); + + saveDeck(); +} + +export function addColumnWidget(id: Column['id'], widget: ColumnWidget) { + const columns = copy(deckStore.state.columns); + const columnIndex = deckStore.state.columns.findIndex(c => c.id === id); + const column = copy(deckStore.state.columns[columnIndex]); + if (column == null) return; + if (column.widgets == null) column.widgets = []; + column.widgets.unshift(widget); + columns[columnIndex] = column; + deckStore.set('columns', columns); + saveDeck(); +} + +export function removeColumnWidget(id: Column['id'], widget: ColumnWidget) { + const columns = copy(deckStore.state.columns); + const columnIndex = deckStore.state.columns.findIndex(c => c.id === id); + const column = copy(deckStore.state.columns[columnIndex]); + if (column == null) return; + column.widgets = column.widgets.filter(w => w.id !== widget.id); + columns[columnIndex] = column; + deckStore.set('columns', columns); + saveDeck(); +} + +export function setColumnWidgets(id: Column['id'], widgets: ColumnWidget[]) { + const columns = copy(deckStore.state.columns); + const columnIndex = deckStore.state.columns.findIndex(c => c.id === id); + const column = copy(deckStore.state.columns[columnIndex]); + if (column == null) return; + column.widgets = widgets; + columns[columnIndex] = column; + deckStore.set('columns', columns); + saveDeck(); +} + +export function updateColumnWidget(id: Column['id'], widgetId: string, widgetData: any) { + const columns = copy(deckStore.state.columns); + const columnIndex = deckStore.state.columns.findIndex(c => c.id === id); + const column = copy(deckStore.state.columns[columnIndex]); + if (column == null) return; + column.widgets = column.widgets.map(w => w.id === widgetId ? { + ...w, + data: widgetData, + } : w); + columns[columnIndex] = column; + deckStore.set('columns', columns); + saveDeck(); +} + +export function updateColumn(id: Column['id'], column: Partial) { + const columns = copy(deckStore.state.columns); + const columnIndex = deckStore.state.columns.findIndex(c => c.id === id); + const currentColumn = copy(deckStore.state.columns[columnIndex]); + if (currentColumn == null) return; + for (const [k, v] of Object.entries(column)) { + currentColumn[k] = v; + } + columns[columnIndex] = currentColumn; + deckStore.set('columns', columns); + saveDeck(); +} diff --git a/packages/client/src/ui/deckold/direct-column.vue b/packages/client/src/ui/deckold/direct-column.vue new file mode 100644 index 000000000..4837c0ce3 --- /dev/null +++ b/packages/client/src/ui/deckold/direct-column.vue @@ -0,0 +1,31 @@ + + + diff --git a/packages/client/src/ui/deckold/list-column.vue b/packages/client/src/ui/deckold/list-column.vue new file mode 100644 index 000000000..a27e65594 --- /dev/null +++ b/packages/client/src/ui/deckold/list-column.vue @@ -0,0 +1,66 @@ + + + + + diff --git a/packages/client/src/ui/deckold/main-column.vue b/packages/client/src/ui/deckold/main-column.vue new file mode 100644 index 000000000..9a5fd43af --- /dev/null +++ b/packages/client/src/ui/deckold/main-column.vue @@ -0,0 +1,68 @@ + + + diff --git a/packages/client/src/ui/deckold/mentions-column.vue b/packages/client/src/ui/deckold/mentions-column.vue new file mode 100644 index 000000000..0b6ca3a23 --- /dev/null +++ b/packages/client/src/ui/deckold/mentions-column.vue @@ -0,0 +1,28 @@ + + + diff --git a/packages/client/src/ui/deckold/notifications-column.vue b/packages/client/src/ui/deckold/notifications-column.vue new file mode 100644 index 000000000..6dd040cb8 --- /dev/null +++ b/packages/client/src/ui/deckold/notifications-column.vue @@ -0,0 +1,38 @@ + + + diff --git a/packages/client/src/ui/deckold/tl-column.vue b/packages/client/src/ui/deckold/tl-column.vue new file mode 100644 index 000000000..f3ecda5aa --- /dev/null +++ b/packages/client/src/ui/deckold/tl-column.vue @@ -0,0 +1,129 @@ + + + + + diff --git a/packages/client/src/ui/deckold/widgets-column.vue b/packages/client/src/ui/deckold/widgets-column.vue new file mode 100644 index 000000000..f181fc328 --- /dev/null +++ b/packages/client/src/ui/deckold/widgets-column.vue @@ -0,0 +1,63 @@ + + + + +