summaryrefslogtreecommitdiff
path: root/src/client
diff options
context:
space:
mode:
Diffstat (limited to 'src/client')
-rw-r--r--src/client/account.ts38
-rwxr-xr-xsrc/client/components/signin.vue6
-rw-r--r--src/client/components/signup.vue4
-rw-r--r--src/client/pages/federation.vue12
-rw-r--r--src/client/pages/settings/general.vue9
-rw-r--r--src/client/pages/settings/privacy.vue2
-rw-r--r--src/client/pages/welcome.setup.vue2
-rw-r--r--src/client/store.ts4
-rw-r--r--src/client/style.scss1
-rw-r--r--src/client/tsconfig.json3
-rw-r--r--src/client/ui/default.vue31
-rw-r--r--src/client/widgets/aichan.vue59
-rw-r--r--src/client/widgets/index.ts2
13 files changed, 146 insertions, 27 deletions
diff --git a/src/client/account.ts b/src/client/account.ts
index ee1d845493..e469bae5a2 100644
--- a/src/client/account.ts
+++ b/src/client/account.ts
@@ -1,4 +1,4 @@
-import { get, set } from '@client/scripts/idb-proxy';
+import { del, get, set } from '@client/scripts/idb-proxy';
import { reactive } from 'vue';
import { apiUrl } from '@client/config';
import { waiting } from '@client/os';
@@ -26,21 +26,33 @@ export async function signout() {
//#region Remove account
const accounts = await getAccounts();
accounts.splice(accounts.findIndex(x => x.id === $i.id), 1);
- set('accounts', accounts);
+
+ if (accounts.length > 0) await set('accounts', accounts);
+ else await del('accounts');
//#endregion
- //#region Remove push notification registration
+ //#region Remove service worker registration
try {
- const registration = await navigator.serviceWorker.ready;
- const push = await registration.pushManager.getSubscription();
- if (!push) return;
- await fetch(`${apiUrl}/sw/unregister`, {
- method: 'POST',
- body: JSON.stringify({
- i: $i.token,
- endpoint: push.endpoint,
- }),
- });
+ if (navigator.serviceWorker.controller) {
+ const registration = await navigator.serviceWorker.ready;
+ const push = await registration.pushManager.getSubscription();
+ if (push) {
+ await fetch(`${apiUrl}/sw/unregister`, {
+ method: 'POST',
+ body: JSON.stringify({
+ i: $i.token,
+ endpoint: push.endpoint,
+ }),
+ });
+ }
+ }
+
+ if (accounts.length === 0) {
+ await navigator.serviceWorker.getRegistrations()
+ .then(registrations => {
+ return Promise.all(registrations.map(registration => registration.unregister()));
+ });
+ }
} catch (e) {}
//#endregion
diff --git a/src/client/components/signin.vue b/src/client/components/signin.vue
index 0094038fb6..c051288d0a 100755
--- a/src/client/components/signin.vue
+++ b/src/client/components/signin.vue
@@ -111,7 +111,9 @@ export default defineComponent({
onLogin(res) {
if (this.autoSet) {
- login(res.i);
+ return login(res.i);
+ } else {
+ return;
}
},
@@ -144,7 +146,7 @@ export default defineComponent({
});
}).then(res => {
this.$emit('login', res);
- this.onLogin(res);
+ return this.onLogin(res);
}).catch(err => {
if (err === null) return;
os.dialog({
diff --git a/src/client/components/signup.vue b/src/client/components/signup.vue
index d584b97209..d332274111 100644
--- a/src/client/components/signup.vue
+++ b/src/client/components/signup.vue
@@ -178,14 +178,14 @@ export default defineComponent({
'hcaptcha-response': this.hCaptchaResponse,
'g-recaptcha-response': this.reCaptchaResponse,
}).then(() => {
- os.api('signin', {
+ return os.api('signin', {
username: this.username,
password: this.password
}).then(res => {
this.$emit('signup', res);
if (this.autoSet) {
- login(res.i);
+ return login(res.i);
}
});
}).catch(() => {
diff --git a/src/client/pages/federation.vue b/src/client/pages/federation.vue
index f4ab9d0ec3..2afe70eea6 100644
--- a/src/client/pages/federation.vue
+++ b/src/client/pages/federation.vue
@@ -28,14 +28,14 @@
<option value="-following">{{ $ts.following }} ({{ $ts.ascendingOrder }})</option>
<option value="+followers">{{ $ts.followers }} ({{ $ts.descendingOrder }})</option>
<option value="-followers">{{ $ts.followers }} ({{ $ts.ascendingOrder }})</option>
- <option value="+caughtAt">{{ $ts.caughtAt }} ({{ $ts.descendingOrder }})</option>
- <option value="-caughtAt">{{ $ts.caughtAt }} ({{ $ts.ascendingOrder }})</option>
- <option value="+lastCommunicatedAt">{{ $ts.lastCommunicatedAt }} ({{ $ts.descendingOrder }})</option>
- <option value="-lastCommunicatedAt">{{ $ts.lastCommunicatedAt }} ({{ $ts.ascendingOrder }})</option>
+ <option value="+caughtAt">{{ $ts.registeredAt }} ({{ $ts.descendingOrder }})</option>
+ <option value="-caughtAt">{{ $ts.registeredAt }} ({{ $ts.ascendingOrder }})</option>
+ <option value="+lastCommunicatedAt">{{ $ts.lastCommunication }} ({{ $ts.descendingOrder }})</option>
+ <option value="-lastCommunicatedAt">{{ $ts.lastCommunication }} ({{ $ts.ascendingOrder }})</option>
<option value="+driveUsage">{{ $ts.driveUsage }} ({{ $ts.descendingOrder }})</option>
<option value="-driveUsage">{{ $ts.driveUsage }} ({{ $ts.ascendingOrder }})</option>
- <option value="+driveFiles">{{ $ts.driveFiles }} ({{ $ts.descendingOrder }})</option>
- <option value="-driveFiles">{{ $ts.driveFiles }} ({{ $ts.ascendingOrder }})</option>
+ <option value="+driveFiles">{{ $ts.driveFilesCount }} ({{ $ts.descendingOrder }})</option>
+ <option value="-driveFiles">{{ $ts.driveFilesCount }} ({{ $ts.ascendingOrder }})</option>
</MkSelect>
</div>
</div>
diff --git a/src/client/pages/settings/general.vue b/src/client/pages/settings/general.vue
index cfa8107d28..f8e8e6b24b 100644
--- a/src/client/pages/settings/general.vue
+++ b/src/client/pages/settings/general.vue
@@ -45,6 +45,10 @@
</FormSwitch>
</FormGroup>
+ <FormGroup>
+ <FormSwitch v-model:value="aiChanMode">{{ $ts.aiChanMode }}</FormSwitch>
+ </FormGroup>
+
<FormRadios v-model="fontSize">
<template #desc>{{ $ts.fontSize }}</template>
<option value="small"><span style="font-size: 14px;">Aa</span></option>
@@ -149,6 +153,7 @@ export default defineComponent({
enableInfiniteScroll: defaultStore.makeGetterSetter('enableInfiniteScroll'),
useReactionPickerForContextMenu: defaultStore.makeGetterSetter('useReactionPickerForContextMenu'),
squareAvatars: defaultStore.makeGetterSetter('squareAvatars'),
+ aiChanMode: defaultStore.makeGetterSetter('aiChanMode'),
},
watch: {
@@ -184,6 +189,10 @@ export default defineComponent({
this.reloadAsk();
},
+ aiChanMode() {
+ this.reloadAsk();
+ },
+
showGapBetweenNotesInTimeline() {
this.reloadAsk();
},
diff --git a/src/client/pages/settings/privacy.vue b/src/client/pages/settings/privacy.vue
index 4095e744c2..46d8c17ca2 100644
--- a/src/client/pages/settings/privacy.vue
+++ b/src/client/pages/settings/privacy.vue
@@ -28,6 +28,7 @@
</FormSelect>
<FormSwitch v-model:value="defaultNoteLocalOnly">{{ $ts._visibility.localOnly }}</FormSwitch>
</FormGroup>
+ <FormSwitch v-model:value="keepCw" @update:value="save()">{{ $ts.keepCw }}</FormSwitch>
</FormBase>
</template>
@@ -69,6 +70,7 @@ export default defineComponent({
defaultNoteVisibility: defaultStore.makeGetterSetter('defaultNoteVisibility'),
defaultNoteLocalOnly: defaultStore.makeGetterSetter('defaultNoteLocalOnly'),
rememberNoteVisibility: defaultStore.makeGetterSetter('rememberNoteVisibility'),
+ keepCw: defaultStore.makeGetterSetter('keepCw'),
},
created() {
diff --git a/src/client/pages/welcome.setup.vue b/src/client/pages/welcome.setup.vue
index de844ece1c..d0091bef67 100644
--- a/src/client/pages/welcome.setup.vue
+++ b/src/client/pages/welcome.setup.vue
@@ -53,7 +53,7 @@ export default defineComponent({
username: this.username,
password: this.password,
}).then(res => {
- login(res.i);
+ return login(res.token);
}).catch(() => {
this.submitting = false;
diff --git a/src/client/store.ts b/src/client/store.ts
index 4c4a7d93e9..e4b762873d 100644
--- a/src/client/store.ts
+++ b/src/client/store.ts
@@ -210,6 +210,10 @@ export const defaultStore = markRaw(new Storage('base', {
where: 'device',
default: ''
},
+ aiChanMode: {
+ where: 'device',
+ default: false
+ },
}));
// TODO: 他のタブと永続化されたstateを同期
diff --git a/src/client/style.scss b/src/client/style.scss
index 269cf88939..6ab5e796bd 100644
--- a/src/client/style.scss
+++ b/src/client/style.scss
@@ -159,7 +159,6 @@ hr {
display: inline-block;
padding: 0;
margin: 0; // for Safari
- width: max-content;
background: none;
border: none;
cursor: pointer;
diff --git a/src/client/tsconfig.json b/src/client/tsconfig.json
index ac7ef7ddfc..7a26047ddf 100644
--- a/src/client/tsconfig.json
+++ b/src/client/tsconfig.json
@@ -21,7 +21,8 @@
"baseUrl": ".",
"paths": {
"@/*": ["../*"],
- "@client/*": ["./*"]
+ "@client/*": ["./*"],
+ "@lib/*": ["../../lib/*"],
},
"typeRoots": [
"node_modules/@types",
diff --git a/src/client/ui/default.vue b/src/client/ui/default.vue
index 23b63114cc..eef693faef 100644
--- a/src/client/ui/default.vue
+++ b/src/client/ui/default.vue
@@ -54,12 +54,14 @@
<XWidgets v-if="widgetsShowing" class="tray"/>
</transition>
+ <iframe v-if="$store.state.aiChanMode" class="ivnzpscs" ref="live2d" src="https://misskey-dev.github.io/mascot-web/?scale=2&y=1.4"></iframe>
+
<XCommon/>
</div>
</template>
<script lang="ts">
-import { defineComponent, defineAsyncComponent } from 'vue';
+import { defineComponent, defineAsyncComponent, markRaw } from 'vue';
import { instanceName } from '@client/config';
import { StickySidebar } from '@client/scripts/sticky-sidebar';
import XSidebar from './default.sidebar.vue';
@@ -131,6 +133,19 @@ export default defineComponent({
this.isMobile = (window.innerWidth <= MOBILE_THRESHOLD);
this.isDesktop = (window.innerWidth >= DESKTOP_THRESHOLD);
}, { passive: true });
+
+ if (this.$store.state.aiChanMode) {
+ const iframeRect = this.$refs.live2d.getBoundingClientRect();
+ window.addEventListener('mousemove', ev => {
+ this.$refs.live2d.contentWindow.postMessage({
+ type: 'moveCursor',
+ body: {
+ x: ev.clientX - iframeRect.left,
+ y: ev.clientY - iframeRect.top,
+ }
+ }, '*');
+ }, { passive: true });
+ }
},
methods: {
@@ -201,6 +216,10 @@ export default defineComponent({
}
}], e);
},
+
+ onAiClick(ev) {
+ //if (this.live2d) this.live2d.click(ev);
+ }
}
});
</script>
@@ -458,5 +477,15 @@ export default defineComponent({
overflow: auto;
background: var(--bg);
}
+
+ > .ivnzpscs {
+ position: fixed;
+ bottom: 0;
+ right: 0;
+ width: 300px;
+ height: 600px;
+ border: none;
+ pointer-events: none;
+ }
}
</style>
diff --git a/src/client/widgets/aichan.vue b/src/client/widgets/aichan.vue
new file mode 100644
index 0000000000..06c49090a1
--- /dev/null
+++ b/src/client/widgets/aichan.vue
@@ -0,0 +1,59 @@
+<template>
+<MkContainer :naked="props.transparent" :show-header="false">
+ <iframe class="dedjhjmo" ref="live2d" @click="touched" src="https://misskey-dev.github.io/mascot-web/?scale=1.5&y=1.1&eyeY=100"></iframe>
+</MkContainer>
+</template>
+
+<script lang="ts">
+import { defineComponent, markRaw } from 'vue';
+import define from './define';
+import MkContainer from '@client/components/ui/container.vue';
+import * as os from '@client/os';
+
+const widget = define({
+ name: 'ai',
+ props: () => ({
+ transparent: {
+ type: 'boolean',
+ default: false,
+ },
+ })
+});
+
+export default defineComponent({
+ extends: widget,
+ components: {
+ MkContainer,
+ },
+ data() {
+ return {
+ };
+ },
+ mounted() {
+ window.addEventListener('mousemove', ev => {
+ const iframeRect = this.$refs.live2d.getBoundingClientRect();
+ this.$refs.live2d.contentWindow.postMessage({
+ type: 'moveCursor',
+ body: {
+ x: ev.clientX - iframeRect.left,
+ y: ev.clientY - iframeRect.top,
+ }
+ }, '*');
+ }, { passive: true });
+ },
+ methods: {
+ touched() {
+ //if (this.live2d) this.live2d.changeExpression('gurugurume');
+ }
+ }
+});
+</script>
+
+<style lang="scss" scoped>
+.dedjhjmo {
+ width: 100%;
+ height: 350px;
+ border: none;
+ pointer-events: none;
+}
+</style>
diff --git a/src/client/widgets/index.ts b/src/client/widgets/index.ts
index 38cb85494a..51a82af080 100644
--- a/src/client/widgets/index.ts
+++ b/src/client/widgets/index.ts
@@ -19,6 +19,7 @@ export default function(app: App) {
app.component('MkwJobQueue', defineAsyncComponent(() => import('./job-queue.vue')));
app.component('MkwButton', defineAsyncComponent(() => import('./button.vue')));
app.component('MkwAiscript', defineAsyncComponent(() => import('./aiscript.vue')));
+ app.component('MkwAichan', defineAsyncComponent(() => import('./aichan.vue')));
}
export const widgets = [
@@ -40,4 +41,5 @@ export const widgets = [
'jobQueue',
'button',
'aiscript',
+ 'aichan',
];