feat: follow-me
This commit is contained in:
parent
af109b45ef
commit
22b52ac3d3
5 changed files with 107 additions and 3 deletions
|
@ -1011,6 +1011,8 @@ isSystemAccount: "This account is created and automatically operated by the syst
|
|||
Please do not moderate, edit, delete, or otherwise tamper with this account, or
|
||||
it may break your server."
|
||||
typeToConfirm: "Please enter {x} to confirm"
|
||||
useThisAccountConfirm: "Do you want to continue with this account?"
|
||||
inputAccountId: "Please input your account (e.g., @firefish@info.firefish.dev )"
|
||||
deleteAccount: "Delete account"
|
||||
document: "Documentation"
|
||||
numberOfPageCache: "Number of cached pages"
|
||||
|
@ -1158,6 +1160,8 @@ confirm: "Confirm"
|
|||
importZip: "Import ZIP"
|
||||
exportZip: "Export ZIP"
|
||||
getQrCode: "Get QR code"
|
||||
remoteFollow: "Remote Follow"
|
||||
remoteFollowUrl: "Remote Follow URL"
|
||||
emojiPackCreator: "Emoji pack creator"
|
||||
indexable: "Indexable"
|
||||
indexableDescription: "Allow built-in search to show your public posts"
|
||||
|
|
|
@ -879,6 +879,8 @@ driveCapOverrideCaption: "输入 0 或以下的值将容量重置为默认值。
|
|||
requireAdminForView: "您需要使用管理员账号登录才能查看。"
|
||||
isSystemAccount: "该账号由系统自动创建。请不要修改、编辑、删除或以其它方式篡改这个账号,否则可能会破坏您的服务器。"
|
||||
typeToConfirm: "输入 {x} 以确认操作"
|
||||
useThisAccountConfirm: "您想使用此帐户继续执行此操作吗?"
|
||||
inputAccountId: "请输入您的帐户(例如 @firefish@info.firefish.dev )"
|
||||
deleteAccount: "删除账号"
|
||||
document: "文档"
|
||||
numberOfPageCache: "缓存页数"
|
||||
|
@ -1975,6 +1977,8 @@ confirm: 确认
|
|||
importZip: 导入 ZIP
|
||||
exportZip: 导出 ZIP
|
||||
getQrCode: "获取二维码"
|
||||
remoteFollow: "远程关注"
|
||||
remoteFollowUrl: "远程关注 URL"
|
||||
emojiPackCreator: 表情包创建工具
|
||||
objectStorageS3ForcePathStyleDesc: 打开此选项可构建格式为 "s3.amazonaws.com/<bucket>/" 而非 "<bucket>.s3.amazonaws.com"
|
||||
的端点 URL。
|
||||
|
|
78
packages/client/src/pages/follow-me.vue
Normal file
78
packages/client/src/pages/follow-me.vue
Normal file
|
@ -0,0 +1,78 @@
|
|||
<template>
|
||||
<div class="mk-follow-page"></div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { acct } from "firefish-js";
|
||||
import * as os from "@/os";
|
||||
import { i18n } from "@/i18n";
|
||||
import { host as hostRaw } from "@/config";
|
||||
import { isSignedIn, me } from "@/me";
|
||||
import { waiting } from "@/os";
|
||||
|
||||
const acctUri = new URL(location.href).searchParams.get("acct");
|
||||
if (acctUri == null) {
|
||||
throw new Error("acct required");
|
||||
}
|
||||
|
||||
let useThisAccount = isSignedIn(me) ? true : false;
|
||||
|
||||
// If the user is already logged in, ask whether to follow using the current account.
|
||||
if (useThisAccount) {
|
||||
const { canceled } = await os.confirm({
|
||||
type: "question",
|
||||
text: i18n.ts.useThisAccountConfirm,
|
||||
});
|
||||
if (!canceled) {
|
||||
waiting();
|
||||
window.location.href = `/authorize-follow?acct=${acctUri}`;
|
||||
} else {
|
||||
useThisAccount = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (!useThisAccount) {
|
||||
// Ask the user what the account ID is
|
||||
const remoteAccountId = await os.inputText({
|
||||
text: i18n.ts.inputAccountId,
|
||||
});
|
||||
|
||||
// If the user do not want enter uri, the user will be redirected to the user page.
|
||||
if (!remoteAccountId.result) {
|
||||
waiting();
|
||||
window.location.href = `/@${acctUri}`;
|
||||
} else {
|
||||
const remoteAcctInfo = acct.parse(remoteAccountId.result);
|
||||
|
||||
// If the user on this server, redirect directly
|
||||
if (remoteAcctInfo.host === hostRaw || remoteAcctInfo.host === null) {
|
||||
waiting();
|
||||
window.location.href = `/authorize-follow?acct=${acctUri}`;
|
||||
} else {
|
||||
waiting();
|
||||
// If not, find the interaction url through webfinger interface
|
||||
fetch(
|
||||
`https://${remoteAcctInfo.host}/.well-known/webfinger?resource=${remoteAcctInfo.username}@${remoteAcctInfo.host}`,
|
||||
{
|
||||
method: "GET",
|
||||
},
|
||||
)
|
||||
.then((response) => response.json())
|
||||
.then((data) => {
|
||||
const subscribeUri = data.links.find(
|
||||
(link) => link.rel === "http://ostatus.org/schema/1.0/subscribe",
|
||||
).template;
|
||||
window.location.href = subscribeUri.replace(
|
||||
"{uri}",
|
||||
acctUri.includes("@") ? acctUri : `${acctUri}@${hostRaw}`,
|
||||
);
|
||||
})
|
||||
.catch((e) => {
|
||||
// TODO: It would be better to provide more information, but the priority of
|
||||
// waiting component is too high and the pop-up window will be blocked.
|
||||
window.location.href = `/@${acctUri}`;
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
|
@ -325,6 +325,10 @@ export const routes: RouteDef[] = [
|
|||
component: page(() => import("./pages/follow.vue")),
|
||||
loginRequired: true,
|
||||
},
|
||||
{
|
||||
path: "/follow-me",
|
||||
component: page(() => import("./pages/follow-me.vue")),
|
||||
},
|
||||
{
|
||||
path: "/authorize_interaction",
|
||||
component: page(() => import("./pages/authorize_interaction.vue")),
|
||||
|
|
|
@ -281,6 +281,13 @@ export function getUserMenu(user, router: Router = mainRouter) {
|
|||
copyToClipboard(`https://${host}/@${user.username}.json`);
|
||||
},
|
||||
},
|
||||
{
|
||||
icon: `${icon("ph-hand-waving")}`,
|
||||
text: i18n.ts.remoteFollowUrl,
|
||||
action: () => {
|
||||
copyToClipboard(`https://${host}/follow-me?acct=${user.username}`);
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
|
@ -290,13 +297,20 @@ export function getUserMenu(user, router: Router = mainRouter) {
|
|||
os.post({ specified: user });
|
||||
},
|
||||
},
|
||||
!isSignedIn(me)
|
||||
? {
|
||||
icon: `${icon("ph-hand-waving")}`,
|
||||
text: i18n.ts.remoteFollow,
|
||||
action: () => {
|
||||
router.push(`/follow-me?acct=${user.username}`);
|
||||
},
|
||||
}
|
||||
: undefined,
|
||||
{
|
||||
icon: "ph-qr-code ph-bold ph-lg",
|
||||
text: i18n.ts.getQrCode,
|
||||
action: () => {
|
||||
os.displayQrCode(
|
||||
`https://${host}/authorize-follow?acct=${user.username}`,
|
||||
);
|
||||
os.displayQrCode(`https://${host}/follow-me?acct=${user.username}`);
|
||||
},
|
||||
},
|
||||
isSignedIn(me) && me.id !== user.id
|
||||
|
|
Loading…
Reference in a new issue