feat: ability to replace chat button with account menu on mobile (close #9)

This commit is contained in:
naskya 2023-07-20 09:03:56 +00:00
parent c927443994
commit a7c402fd2f
Signed by: naskya
GPG key ID: 164DFF24E2D40139
7 changed files with 112 additions and 39 deletions

View file

@ -6,6 +6,8 @@
## 主要な変更点
- モバイル表示の下部のチャットボタンをアカウント切り替えボタンに変更可能に
- これ無しで PWA で複数アカウントを使おうとすると腱鞘炎になる
- ローカルタイムラインの位置をグローバルタイムラインの直前に移動
- ローカルタイムラインよりもソーシャルタイムラインのほうが使いやすいと考えたため
- 「Firefish について」のページに Misskey の主要な貢献者を表示

View file

@ -1129,6 +1129,8 @@ showPreviewByDefault: "Show preview in posting form by default"
originalFeature: "original"
preventMisclick: "Accidental click prevention"
hideFollowButtons: "Hide follow buttons in notifications and user pages"
forMobile: "Mobile"
replaceChatButtonWithAccountButton: "Replace chat button at the bottom with account switch button"
_sensitiveMediaDetection:
description: "Reduces the effort of server moderation through automatically recognizing

View file

@ -989,6 +989,8 @@ showPreviewByDefault: "投稿画面でプレビュー表示をデフォルトで
originalFeature: "独自機能"
preventMisclick: "誤タップ防止"
hideFollowButtons: "新規フォロワーの通知とユーザーページの ... の隣にあるフォローボタンを隠す"
forMobile: "モバイル向け"
replaceChatButtonWithAccountButton: "画面下部のチャットのボタンをアカウント切り替えボタンに変更する"
_sensitiveMediaDetection:
description: "機械学習を使って自動でセンシティブなメディアを検出し、モデレーションに役立てられます。サーバーの負荷が少し増えます。"

View file

@ -154,6 +154,7 @@ export async function openAccountMenu(
onChoose?: (account: misskey.entities.UserDetailed) => void;
},
ev: MouseEvent,
isMobile?: boolean,
) {
function showSigninDialog() {
popup(
@ -230,48 +231,70 @@ export async function openAccountMenu(
popupMenu(
[
...[
{
type: "link",
text: i18n.ts.profile,
to: `/@${$i.username}`,
avatar: $i,
},
null,
...(isMobile ?? false
? [
{
type: "parent",
icon: "ph-plus ph-bold ph-lg",
text: i18n.ts.addAccount,
children: [
{
text: i18n.ts.existingAccount,
action: () => {
showSigninDialog();
},
},
{
text: i18n.ts.createAccount,
action: () => {
createAccount();
},
},
],
},
]
: [
{
type: "link",
text: i18n.ts.profile,
to: `/@${$i.username}`,
avatar: $i,
},
null,
]),
...(opts.includeCurrentAccount ? [createItem($i)] : []),
...accountItemPromises,
{
type: "parent",
icon: "ph-plus ph-bold ph-lg",
text: i18n.ts.addAccount,
children: [
{
text: i18n.ts.existingAccount,
action: () => {
showSigninDialog();
...(isMobile ?? false
? [
null,
{
type: "link",
text: i18n.ts.profile,
to: `/@${$i.username}`,
avatar: $i,
},
},
{
text: i18n.ts.createAccount,
action: () => {
createAccount();
]
: [
{
type: "parent",
icon: "ph-plus ph-bold ph-lg",
text: i18n.ts.addAccount,
children: [
{
text: i18n.ts.existingAccount,
action: () => {
showSigninDialog();
},
},
{
text: i18n.ts.createAccount,
action: () => {
createAccount();
},
},
],
},
},
],
},
{
type: "link",
icon: "ph-users ph-bold ph-lg",
text: i18n.ts.manageAccounts,
to: "/settings/accounts",
},
{
type: "button",
icon: "ph-sign-out ph-bold ph-lg",
text: i18n.ts.logout,
action: () => {
signout();
},
},
]),
],
],
ev.currentTarget ?? ev.target,

View file

@ -238,6 +238,18 @@
>
</FormSection>
<FormSection>
<template #label>{{ i18n.ts.forMobile }}</template>
<FormSwitch
v-model="replaceChatButtonWithAccountButton"
class="_formBlock"
>{{ i18n.ts.replaceChatButtonWithAccountButton
}}<span class="_beta">{{
i18n.ts.originalFeature
}}</span></FormSwitch
>
</FormSection>
<FormRange
v-model="numberOfPageCache"
:min="1"
@ -379,6 +391,9 @@ const showTimelineReplies = computed(
const hideFollowButtons = computed(
defaultStore.makeGetterSetter("hideFollowButtons"),
);
const replaceChatButtonWithAccountButton = computed(
defaultStore.makeGetterSetter("replaceChatButtonWithAccountButton"),
);
watch(swipeOnDesktop, () => {
defaultStore.set("swipeOnMobile", true);

View file

@ -350,6 +350,10 @@ export const defaultStore = markRaw(
where: "device",
default: true,
},
replaceChatButtonWithAccountButton: {
where: "device",
default: true,
},
}),
);

View file

@ -86,6 +86,20 @@
</div>
</button>
<button
v-if="useAccountButton"
:aria-label="i18n.t('accounts')"
class="button messaging _button"
@click="openAccountMenu"
>
<div
class="button-wrapper"
:class="buttonAnimIndex === 2 ? 'on' : ''"
>
<i class="ph-users ph-bold ph-lg"></i>
</div>
</button>
<button
v-else
:aria-label="i18n.t('messaging')"
class="button messaging _button"
@click="
@ -181,7 +195,7 @@ import * as os from "@/os";
import { defaultStore } from "@/store";
import { navbarItemDef } from "@/navbar";
import { i18n } from "@/i18n";
import { $i } from "@/account";
import { $i, openAccountMenu as openAccountMenu_ } from "@/account";
import { mainRouter } from "@/router";
import {
provideMetadataReceiver,
@ -207,6 +221,17 @@ window.addEventListener("resize", () => {
deviceKind === "smartphone" || window.innerWidth <= MOBILE_THRESHOLD;
});
const useAccountButton = defaultStore.state.replaceChatButtonWithAccountButton;
const openAccountMenu = (ev: MouseEvent) => {
openAccountMenu_(
{
withExtraOperation: true,
},
ev,
isMobile.value,
);
};
const buttonAnimIndex = ref(0);
const drawerMenuShowing = ref(false);