diff --git a/locales/en-US.yml b/locales/en-US.yml
index 36a733b94..45ffe4cb2 100644
--- a/locales/en-US.yml
+++ b/locales/en-US.yml
@@ -1339,3 +1339,8 @@ _translationService:
_libreTranslate:
endpoint: "LibreTranslate API Endpoint"
authKey: "LibreTranslate Auth Key (optional)"
+_remoteInteract:
+ title: "I'm sorry, I'm afraid I can't do that."
+ description: "You cannot perform this action right now. You probably need to do it on your own instance, or sign in."
+ urlInstructions: "You can copy this URL. If you paste it into the search field on your instance, you should be taken to the right location."
+ url: "URL"
diff --git a/packages/client/src/components/key-value.vue b/packages/client/src/components/key-value.vue
index 2b9c735dd..079c7fbb8 100644
--- a/packages/client/src/components/key-value.vue
+++ b/packages/client/src/components/key-value.vue
@@ -5,6 +5,7 @@
+
diff --git a/packages/client/src/components/note-detailed.vue b/packages/client/src/components/note-detailed.vue
index 3549ef953..83d8b02e2 100644
--- a/packages/client/src/components/note-detailed.vue
+++ b/packages/client/src/components/note-detailed.vue
@@ -126,7 +126,7 @@ import XRenoteButton from './renote-button.vue';
import MkUrlPreview from '@/components/url-preview.vue';
import MkInstanceTicker from '@/components/instance-ticker.vue';
import MkVisibility from '@/components/visibility.vue';
-import { pleaseLogin } from '@/scripts/please-login';
+import { pleaseLoginOrRemote, urlForNote } from '@/scripts/please-login';
import { checkWordMute } from '@/scripts/check-word-mute';
import { userPage } from '@/filters/user';
import { notePage } from '@/filters/note';
@@ -195,7 +195,8 @@ useNoteCapture({
});
function reply(viaKeyboard = false): void {
- pleaseLogin();
+ pleaseLoginOrRemote(urlForNote(appearNote));
+
os.post({
reply: appearNote,
animation: !viaKeyboard,
@@ -205,7 +206,8 @@ function reply(viaKeyboard = false): void {
}
function react(): void {
- pleaseLogin();
+ pleaseLoginOrRemote(urlForNote(appearNote));
+
blur();
reactionPicker.show(reactButton.value, reaction => {
os.api('notes/reactions/create', {
diff --git a/packages/client/src/components/note.vue b/packages/client/src/components/note.vue
index b0938b3c0..8324f083a 100644
--- a/packages/client/src/components/note.vue
+++ b/packages/client/src/components/note.vue
@@ -115,7 +115,7 @@ import XRenoteButton from './renote-button.vue';
import MkUrlPreview from '@/components/url-preview.vue';
import MkInstanceTicker from '@/components/instance-ticker.vue';
import MkVisibility from '@/components/visibility.vue';
-import { pleaseLogin } from '@/scripts/please-login';
+import { pleaseLoginOrRemote, urlForNote } from '@/scripts/please-login';
import { focusPrev, focusNext } from '@/scripts/focus';
import { checkWordMute } from '@/scripts/check-word-mute';
import { userPage } from '@/filters/user';
@@ -188,7 +188,8 @@ useNoteCapture({
});
function reply(viaKeyboard = false): void {
- pleaseLogin();
+ pleaseLoginOrRemote(urlForNote(appearNote));
+
os.post({
reply: appearNote,
animation: !viaKeyboard,
@@ -198,7 +199,8 @@ function reply(viaKeyboard = false): void {
}
function react(): void {
- pleaseLogin();
+ pleaseLoginOrRemote(urlForNote(appearNote));
+
blur();
reactionPicker.show(reactButton.value, reaction => {
os.api('notes/reactions/create', {
diff --git a/packages/client/src/components/poll.vue b/packages/client/src/components/poll.vue
index 92f0961c9..db1363d28 100644
--- a/packages/client/src/components/poll.vue
+++ b/packages/client/src/components/poll.vue
@@ -25,7 +25,7 @@
import { computed, ref } from 'vue';
import * as foundkey from 'foundkey-js';
import { sum } from '@/scripts/array';
-import { pleaseLogin } from '@/scripts/please-login';
+import { pleaseLoginOrRemote, urlForNote } from '@/scripts/please-login';
import * as os from '@/os';
import { i18n } from '@/i18n';
import { useInterval } from '@/scripts/use-interval';
@@ -68,7 +68,7 @@ if (props.note.poll.expiresAt) {
}
const vote = async (id) => {
- pleaseLogin();
+ pleaseLoginOrRemote(urlForNote(props.note));
if (props.readOnly || closed.value || isVoted.value) return;
diff --git a/packages/client/src/components/remote-interact.vue b/packages/client/src/components/remote-interact.vue
new file mode 100644
index 000000000..c17926435
--- /dev/null
+++ b/packages/client/src/components/remote-interact.vue
@@ -0,0 +1,88 @@
+
+
+ {{ i18n.ts._remoteInteract.title }}
+
+
+
{{ i18n.ts._remoteInteract.description }}
+
+
{{ i18n.ts._remoteInteract.urlInstructions }}
+ {{ remoteUrl }}
+
+
+
+
+
+
+
+
+
+
diff --git a/packages/client/src/components/renote-button.vue b/packages/client/src/components/renote-button.vue
index 9e4dbb3e6..4f84b783a 100644
--- a/packages/client/src/components/renote-button.vue
+++ b/packages/client/src/components/renote-button.vue
@@ -17,7 +17,7 @@
import { computed, ref } from 'vue';
import { Note } from 'foundkey-js/built/entities';
import XDetails from '@/components/users-tooltip.vue';
-import { pleaseLogin } from '@/scripts/please-login';
+import { pleaseLoginOrRemote, urlForNote } from '@/scripts/please-login';
import * as os from '@/os';
import { $i } from '@/account';
import { useTooltip } from '@/scripts/use-tooltip';
@@ -51,7 +51,8 @@ useTooltip(buttonRef, async (showing) => {
});
function renote(viaKeyboard = false): void {
- pleaseLogin();
+ pleaseLoginOrRemote(urlForNote(props.note));
+
os.popupMenu([{
text: i18n.ts.renote,
icon: 'fas fa-retweet',
diff --git a/packages/client/src/nirax.ts b/packages/client/src/nirax.ts
index 51f1dc20a..795e27eb5 100644
--- a/packages/client/src/nirax.ts
+++ b/packages/client/src/nirax.ts
@@ -2,7 +2,7 @@
import { EventEmitter } from 'eventemitter3';
import { Component, shallowRef, ShallowRef } from 'vue';
-import { pleaseLogin } from '@/scripts/please-login';
+import { pleaseLoginOrPage } from '@/scripts/please-login';
import { safeURIDecode } from '@/scripts/safe-uri-decode';
type RouteDef = {
@@ -174,7 +174,7 @@ export class Router extends EventEmitter<{
}
if (res.route.loginRequired) {
- pleaseLogin('/');
+ pleaseLoginOrPage('/');
}
const isSamePath = beforePath === path;
diff --git a/packages/client/src/scripts/please-login.ts b/packages/client/src/scripts/please-login.ts
index 52862427b..597f32e16 100644
--- a/packages/client/src/scripts/please-login.ts
+++ b/packages/client/src/scripts/please-login.ts
@@ -2,8 +2,10 @@ import { defineAsyncComponent } from 'vue';
import { $i } from '@/account';
import { i18n } from '@/i18n';
import { popup } from '@/os';
+import { url } from '@/config';
+import { entities } from 'foundkey-js';
-export function pleaseLogin(path?: string) {
+export function pleaseLoginOrPage(path?: string) {
if ($i) return;
popup(defineAsyncComponent(() => import('@/components/signin-dialog.vue')), {
@@ -19,3 +21,19 @@ export function pleaseLogin(path?: string) {
if (!path) throw new Error('signin required');
}
+
+export function pleaseLoginOrRemote(remoteUrl: string) {
+ if ($i) return;
+
+ popup(defineAsyncComponent(() => import('@/components/remote-interact.vue')), {
+ remoteUrl,
+ }, {}, 'closed');
+
+ throw new Error('signin required');
+}
+
+export function urlForNote(note: entities.Note): string {
+ return note.url
+ ?? note.uri
+ ?? `${url}/notes/${note.id}`;
+}