summaryrefslogtreecommitdiff
path: root/src/client
diff options
context:
space:
mode:
Diffstat (limited to 'src/client')
-rw-r--r--src/client/app/boot.js9
-rw-r--r--src/client/app/common/scripts/post-form.ts33
-rw-r--r--src/client/app/common/views/components/games/reversi/reversi.game.vue6
-rw-r--r--src/client/app/common/views/components/messaging-room.form.vue22
-rw-r--r--src/client/app/common/views/components/mfm.ts12
-rw-r--r--src/client/app/common/views/components/misskey-flavored-markdown.vue4
-rw-r--r--src/client/app/common/views/components/page/page.block.vue (renamed from src/client/app/common/views/pages/page/page.block.vue)0
-rw-r--r--src/client/app/common/views/components/page/page.button.vue (renamed from src/client/app/common/views/pages/page/page.button.vue)17
-rw-r--r--src/client/app/common/views/components/page/page.counter.vue (renamed from src/client/app/common/views/pages/page/page.counter.vue)0
-rw-r--r--src/client/app/common/views/components/page/page.if.vue (renamed from src/client/app/common/views/pages/page/page.if.vue)0
-rw-r--r--src/client/app/common/views/components/page/page.image.vue (renamed from src/client/app/common/views/pages/page/page.image.vue)0
-rw-r--r--src/client/app/common/views/components/page/page.number-input.vue (renamed from src/client/app/common/views/pages/page/page.number-input.vue)0
-rw-r--r--src/client/app/common/views/components/page/page.post.vue (renamed from src/client/app/common/views/pages/page/page.post.vue)0
-rw-r--r--src/client/app/common/views/components/page/page.section.vue (renamed from src/client/app/common/views/pages/page/page.section.vue)0
-rw-r--r--src/client/app/common/views/components/page/page.switch.vue (renamed from src/client/app/common/views/pages/page/page.switch.vue)0
-rw-r--r--src/client/app/common/views/components/page/page.text-input.vue (renamed from src/client/app/common/views/pages/page/page.text-input.vue)0
-rw-r--r--src/client/app/common/views/components/page/page.text.vue (renamed from src/client/app/common/views/pages/page/page.text.vue)0
-rw-r--r--src/client/app/common/views/components/page/page.textarea-input.vue (renamed from src/client/app/common/views/pages/page/page.textarea-input.vue)0
-rw-r--r--src/client/app/common/views/components/page/page.textarea.vue (renamed from src/client/app/common/views/pages/page/page.textarea.vue)0
-rw-r--r--src/client/app/common/views/components/page/page.vue (renamed from src/client/app/common/views/pages/page/page.vue)92
-rw-r--r--src/client/app/common/views/components/poll.vue2
-rw-r--r--src/client/app/common/views/components/settings/2fa.vue16
-rw-r--r--src/client/app/common/views/components/settings/app-type.vue36
-rw-r--r--src/client/app/common/views/components/settings/drive.vue36
-rw-r--r--src/client/app/common/views/components/settings/settings.vue27
-rw-r--r--src/client/app/common/views/components/signin.vue6
-rw-r--r--src/client/app/common/views/components/uploader.vue5
-rw-r--r--src/client/app/common/views/components/url-preview.vue1
-rw-r--r--src/client/app/common/views/components/user-list.vue2
-rw-r--r--src/client/app/common/views/components/user-name.vue2
-rw-r--r--src/client/app/common/views/deck/deck.notification.vue6
-rw-r--r--src/client/app/common/views/deck/deck.page-column.vue69
-rw-r--r--src/client/app/common/views/deck/deck.user-column.home.vue7
-rw-r--r--src/client/app/common/views/deck/deck.user-column.vue2
-rw-r--r--src/client/app/common/views/pages/follow.vue2
-rw-r--r--src/client/app/common/views/pages/page-editor/els/page-editor.el.button.vue28
-rw-r--r--src/client/app/common/views/pages/page-editor/page-editor.vue6
-rw-r--r--src/client/app/common/views/pages/page.vue63
-rw-r--r--src/client/app/common/views/widgets/post-form.vue24
-rw-r--r--src/client/app/desktop/script.ts4
-rw-r--r--src/client/app/desktop/views/components/drive.folder.vue48
-rw-r--r--src/client/app/desktop/views/components/notifications.vue12
-rw-r--r--src/client/app/desktop/views/home/home.vue4
-rw-r--r--src/client/app/desktop/views/home/timeline.vue28
-rw-r--r--src/client/app/desktop/views/home/user/user.header.vue2
-rw-r--r--src/client/app/desktop/views/home/user/user.home.vue5
-rw-r--r--src/client/app/desktop/views/widgets/profile.vue2
-rw-r--r--src/client/app/mobile/script.ts3
-rw-r--r--src/client/app/mobile/views/components/notification.vue6
-rw-r--r--src/client/app/mobile/views/pages/settings.vue2
-rw-r--r--src/client/app/mobile/views/pages/user/home.vue8
-rw-r--r--src/client/app/mobile/views/pages/user/index.vue2
-rw-r--r--src/client/app/store.ts4
53 files changed, 540 insertions, 125 deletions
diff --git a/src/client/app/boot.js b/src/client/app/boot.js
index 6cb1488e40..583cc4fc8b 100644
--- a/src/client/app/boot.js
+++ b/src/client/app/boot.js
@@ -84,7 +84,14 @@
// Detect the user agent
const ua = navigator.userAgent.toLowerCase();
- const isMobile = /mobile|iphone|ipad|android/.test(ua);
+ let isMobile = /mobile|iphone|ipad|android/.test(ua) || window.innerWidth < 576;
+ if (settings && settings.device.appTypeForce) {
+ if (settings.device.appTypeForce === 'mobile') {
+ isMobile = true;
+ } else if (settings.device.appTypeForce === 'desktop') {
+ isMobile = false;
+ }
+ }
// Get the <head> element
const head = document.getElementsByTagName('head')[0];
diff --git a/src/client/app/common/scripts/post-form.ts b/src/client/app/common/scripts/post-form.ts
index 85a578484f..7cf26f65bf 100644
--- a/src/client/app/common/scripts/post-form.ts
+++ b/src/client/app/common/scripts/post-form.ts
@@ -8,6 +8,7 @@ import { host, url } from '../../config';
import i18n from '../../i18n';
import { erase, unique } from '../../../../prelude/array';
import extractMentions from '../../../../misc/extract-mentions';
+import { formatTimeString } from '../../../../misc/format-time-string';
export default (opts) => ({
i18n: i18n(),
@@ -151,9 +152,16 @@ export default (opts) => ({
// 公開以外へのリプライ時は元の公開範囲を引き継ぐ
if (this.reply && ['home', 'followers', 'specified'].includes(this.reply.visibility)) {
this.visibility = this.reply.visibility;
+ if (this.reply.visibility === 'specified') {
+ this.$root.api('users/show', {
+ userIds: this.reply.visibleUserIds.filter(uid => uid !== this.$store.state.i.id && uid !== this.reply.userId)
+ }).then(users => {
+ this.visibleUsers.push(...users);
+ });
+ }
}
- if (this.reply) {
+ if (this.reply && this.reply.userId !== this.$store.state.i.id) {
this.$root.api('users/show', { userId: this.reply.userId }).then(user => {
this.visibleUsers.push(user);
});
@@ -237,8 +245,8 @@ export default (opts) => ({
for (const x of Array.from((this.$refs.file as any).files)) this.upload(x);
},
- upload(file) {
- (this.$refs.uploader as any).upload(file);
+ upload(file: File, name?: string) {
+ (this.$refs.uploader as any).upload(file, this.$store.state.settings.uploadFolder, name);
},
onChangeUploadings(uploads) {
@@ -327,10 +335,23 @@ export default (opts) => ({
if ((e.which == 10 || e.which == 13) && (e.ctrlKey || e.metaKey) && this.canPost) this.post();
},
- async onPaste(e) {
- for (const item of Array.from(e.clipboardData.items)) {
+ async onPaste(e: ClipboardEvent) {
+ for (const { item, i } of Array.from(e.clipboardData.items).map((item, i) => ({item, i}))) {
if (item.kind == 'file') {
- this.upload(item.getAsFile());
+ const file = item.getAsFile();
+ const lio = file.name.lastIndexOf('.');
+ const ext = lio >= 0 ? file.name.slice(lio) : '';
+ const formatted = `${formatTimeString(new Date(file.lastModified), this.$store.state.settings.pastedFileName).replace(/{{number}}/g, `${i + 1}`)}${ext}`;
+ const name = this.$store.state.settings.pasteDialog
+ ? await this.$root.dialog({
+ title: this.$t('@.post-form.enter-file-name'),
+ input: {
+ default: formatted
+ },
+ allowEmpty: false
+ }).then(({ canceled, result }) => canceled ? false : result)
+ : formatted;
+ if (name) this.upload(file, name);
}
}
diff --git a/src/client/app/common/views/components/games/reversi/reversi.game.vue b/src/client/app/common/views/components/games/reversi/reversi.game.vue
index 3f481e8eb5..a7c918aa71 100644
--- a/src/client/app/common/views/components/games/reversi/reversi.game.vue
+++ b/src/client/app/common/views/components/games/reversi/reversi.game.vue
@@ -5,17 +5,17 @@
<div style="overflow: hidden; line-height: 28px;">
<p class="turn" v-if="!iAmPlayer && !game.isEnded">
- <mfm :key="'turn:' + $options.filters.userName(turnUser)" :text="$t('@.reversi.turn-of', { name: $options.filters.userName(turnUser) })" :should-break="false" :plain-text="true" :custom-emojis="turnUser.emojis"/>
+ <mfm :key="'turn:' + $options.filters.userName(turnUser)" :text="$t('@.reversi.turn-of', { name: $options.filters.userName(turnUser) })" :plain="true" :custom-emojis="turnUser.emojis"/>
<mk-ellipsis/>
</p>
<p class="turn" v-if="logPos != logs.length">
- <mfm :key="'past-turn-of:' + $options.filters.userName(turnUser)" :text="$t('@.reversi.past-turn-of', { name: $options.filters.userName(turnUser) })" :should-break="false" :plain-text="true" :custom-emojis="turnUser.emojis"/>
+ <mfm :key="'past-turn-of:' + $options.filters.userName(turnUser)" :text="$t('@.reversi.past-turn-of', { name: $options.filters.userName(turnUser) })" :plain="true" :custom-emojis="turnUser.emojis"/>
</p>
<p class="turn1" v-if="iAmPlayer && !game.isEnded && !isMyTurn">{{ $t('@.reversi.opponent-turn') }}<mk-ellipsis/></p>
<p class="turn2" v-if="iAmPlayer && !game.isEnded && isMyTurn" v-animate-css="{ classes: 'tada', iteration: 'infinite' }">{{ $t('@.reversi.my-turn') }}</p>
<p class="result" v-if="game.isEnded && logPos == logs.length">
<template v-if="game.winner">
- <mfm :key="'won'" :text="$t('@.reversi.won', { name: $options.filters.userName(game.winner) })" :should-break="false" :plain-text="true" :custom-emojis="game.winner.emojis"/>
+ <mfm :key="'won'" :text="$t('@.reversi.won', { name: $options.filters.userName(game.winner) })" :plain="true" :custom-emojis="game.winner.emojis"/>
<span v-if="game.surrendered != null"> ({{ $t('surrendered') }})</span>
</template>
<template v-else>{{ $t('@.reversi.drawn') }}</template>
diff --git a/src/client/app/common/views/components/messaging-room.form.vue b/src/client/app/common/views/components/messaging-room.form.vue
index 1dfb0589e4..bd63bab2c1 100644
--- a/src/client/app/common/views/components/messaging-room.form.vue
+++ b/src/client/app/common/views/components/messaging-room.form.vue
@@ -30,6 +30,7 @@
import Vue from 'vue';
import i18n from '../../../i18n';
import * as autosize from 'autosize';
+import { formatTimeString } from '../../../../../misc/format-time-string';
export default Vue.extend({
i18n: i18n('common/views/components/messaging-room.form.vue'),
@@ -84,13 +85,26 @@ export default Vue.extend({
}
},
methods: {
- onPaste(e) {
+ async onPaste(e: ClipboardEvent) {
const data = e.clipboardData;
const items = data.items;
if (items.length == 1) {
if (items[0].kind == 'file') {
- this.upload(items[0].getAsFile());
+ const file = items[0].getAsFile();
+ const lio = file.name.lastIndexOf('.');
+ const ext = lio >= 0 ? file.name.slice(lio) : '';
+ const formatted = `${formatTimeString(new Date(file.lastModified), this.$store.state.settings.pastedFileName).replace(/{{number}}/g, '1')}${ext}`;
+ const name = this.$store.state.settings.pasteDialog
+ ? await this.$root.dialog({
+ title: this.$t('@.post-form.enter-file-name'),
+ input: {
+ default: formatted
+ },
+ allowEmpty: false
+ }).then(({ canceled, result }) => canceled ? false : result)
+ : formatted;
+ if (name) this.upload(file, name);
}
} else {
if (items[0].kind == 'file') {
@@ -157,8 +171,8 @@ export default Vue.extend({
this.upload((this.$refs.file as any).files[0]);
},
- upload(file) {
- (this.$refs.uploader as any).upload(file);
+ upload(file: File, name?: string) {
+ (this.$refs.uploader as any).upload(file, this.$store.state.settings.uploadFolder, name);
},
onUploaded(file) {
diff --git a/src/client/app/common/views/components/mfm.ts b/src/client/app/common/views/components/mfm.ts
index fa798504c7..561c3d8e30 100644
--- a/src/client/app/common/views/components/mfm.ts
+++ b/src/client/app/common/views/components/mfm.ts
@@ -22,11 +22,11 @@ export default Vue.component('misskey-flavored-markdown', {
type: String,
required: true
},
- shouldBreak: {
+ plain: {
type: Boolean,
- default: true
+ default: false
},
- plainText: {
+ nowrap: {
type: Boolean,
default: false
},
@@ -50,7 +50,7 @@ export default Vue.component('misskey-flavored-markdown', {
render(createElement) {
if (this.text == null || this.text == '') return;
- const ast = (this.plainText ? parsePlain : parse)(this.text);
+ const ast = (this.plain ? parsePlain : parse)(this.text);
let bigCount = 0;
let motionCount = 0;
@@ -60,7 +60,7 @@ export default Vue.component('misskey-flavored-markdown', {
case 'text': {
const text = token.node.props.text.replace(/(\r\n|\n|\r)/g, '\n');
- if (this.shouldBreak) {
+ if (!this.plain) {
const x = text.split('\n')
.map(t => t == '' ? [createElement('br')] : [createElement('span', t), createElement('br')]);
x[x.length - 1].pop();
@@ -270,7 +270,7 @@ export default Vue.component('misskey-flavored-markdown', {
},
props: {
customEmojis: this.customEmojis || customEmojis,
- normal: this.plainText
+ normal: this.plain
}
})];
}
diff --git a/src/client/app/common/views/components/misskey-flavored-markdown.vue b/src/client/app/common/views/components/misskey-flavored-markdown.vue
index a0ecbecbb2..64496f9c84 100644
--- a/src/client/app/common/views/components/misskey-flavored-markdown.vue
+++ b/src/client/app/common/views/components/misskey-flavored-markdown.vue
@@ -1,5 +1,5 @@
<template>
-<mfm-core v-bind="$attrs" class="havbbuyv" :class="{ plain: $attrs['plain-text'] }" v-once/>
+<mfm-core v-bind="$attrs" class="havbbuyv" :class="{ nowrap: $attrs['nowrap'] }" v-once/>
</template>
<script lang="ts">
@@ -17,7 +17,7 @@ export default Vue.extend({
.havbbuyv
white-space pre-wrap
- &.plain
+ &.nowrap
white-space pre
>>> .title
diff --git a/src/client/app/common/views/pages/page/page.block.vue b/src/client/app/common/views/components/page/page.block.vue
index 1c421fc2c0..1c421fc2c0 100644
--- a/src/client/app/common/views/pages/page/page.block.vue
+++ b/src/client/app/common/views/components/page/page.block.vue
diff --git a/src/client/app/common/views/pages/page/page.button.vue b/src/client/app/common/views/components/page/page.button.vue
index 3747be96ce..87112aca0d 100644
--- a/src/client/app/common/views/pages/page/page.button.vue
+++ b/src/client/app/common/views/components/page/page.button.vue
@@ -1,6 +1,6 @@
<template>
<div>
- <ui-button class="kudkigyw" @click="click()">{{ script.interpolate(value.text) }}</ui-button>
+ <ui-button class="kudkigyw" @click="click()" :primary="value.primary">{{ script.interpolate(value.text) }}</ui-button>
</div>
</template>
@@ -27,6 +27,19 @@ export default Vue.extend({
} else if (this.value.action === 'resetRandom') {
this.script.aiScript.updateRandomSeed(Math.random());
this.script.eval();
+ } else if (this.value.action === 'pushEvent') {
+ this.$root.api('page-push', {
+ pageId: this.script.page.id,
+ event: this.value.event,
+ ...(this.value.var ? {
+ var: this.script.vars[this.value.var]
+ } : {})
+ });
+
+ this.$root.dialog({
+ type: 'success',
+ text: this.script.interpolate(this.value.message)
+ });
}
}
}
@@ -36,7 +49,7 @@ export default Vue.extend({
<style lang="stylus" scoped>
.kudkigyw
display inline-block
- min-width 300px
+ min-width 200px
max-width 450px
margin 8px 0
</style>
diff --git a/src/client/app/common/views/pages/page/page.counter.vue b/src/client/app/common/views/components/page/page.counter.vue
index 8d55319fe9..8d55319fe9 100644
--- a/src/client/app/common/views/pages/page/page.counter.vue
+++ b/src/client/app/common/views/components/page/page.counter.vue
diff --git a/src/client/app/common/views/pages/page/page.if.vue b/src/client/app/common/views/components/page/page.if.vue
index 417ef0c553..417ef0c553 100644
--- a/src/client/app/common/views/pages/page/page.if.vue
+++ b/src/client/app/common/views/components/page/page.if.vue
diff --git a/src/client/app/common/views/pages/page/page.image.vue b/src/client/app/common/views/components/page/page.image.vue
index 1285445eb0..1285445eb0 100644
--- a/src/client/app/common/views/pages/page/page.image.vue
+++ b/src/client/app/common/views/components/page/page.image.vue
diff --git a/src/client/app/common/views/pages/page/page.number-input.vue b/src/client/app/common/views/components/page/page.number-input.vue
index 31da37330a..31da37330a 100644
--- a/src/client/app/common/views/pages/page/page.number-input.vue
+++ b/src/client/app/common/views/components/page/page.number-input.vue
diff --git a/src/client/app/common/views/pages/page/page.post.vue b/src/client/app/common/views/components/page/page.post.vue
index cb695e21e9..cb695e21e9 100644
--- a/src/client/app/common/views/pages/page/page.post.vue
+++ b/src/client/app/common/views/components/page/page.post.vue
diff --git a/src/client/app/common/views/pages/page/page.section.vue b/src/client/app/common/views/components/page/page.section.vue
index 03c009d9c3..03c009d9c3 100644
--- a/src/client/app/common/views/pages/page/page.section.vue
+++ b/src/client/app/common/views/components/page/page.section.vue
diff --git a/src/client/app/common/views/pages/page/page.switch.vue b/src/client/app/common/views/components/page/page.switch.vue
index 53695f1b36..53695f1b36 100644
--- a/src/client/app/common/views/pages/page/page.switch.vue
+++ b/src/client/app/common/views/components/page/page.switch.vue
diff --git a/src/client/app/common/views/pages/page/page.text-input.vue b/src/client/app/common/views/components/page/page.text-input.vue
index cf917dd5a8..cf917dd5a8 100644
--- a/src/client/app/common/views/pages/page/page.text-input.vue
+++ b/src/client/app/common/views/components/page/page.text-input.vue
diff --git a/src/client/app/common/views/pages/page/page.text.vue b/src/client/app/common/views/components/page/page.text.vue
index 326fd39050..326fd39050 100644
--- a/src/client/app/common/views/pages/page/page.text.vue
+++ b/src/client/app/common/views/components/page/page.text.vue
diff --git a/src/client/app/common/views/pages/page/page.textarea-input.vue b/src/client/app/common/views/components/page/page.textarea-input.vue
index eece59fefb..eece59fefb 100644
--- a/src/client/app/common/views/pages/page/page.textarea-input.vue
+++ b/src/client/app/common/views/components/page/page.textarea-input.vue
diff --git a/src/client/app/common/views/pages/page/page.textarea.vue b/src/client/app/common/views/components/page/page.textarea.vue
index 03c8542cb0..03c8542cb0 100644
--- a/src/client/app/common/views/pages/page/page.textarea.vue
+++ b/src/client/app/common/views/components/page/page.textarea.vue
diff --git a/src/client/app/common/views/pages/page/page.vue b/src/client/app/common/views/components/page/page.vue
index 96a2cfafb7..99e627fd89 100644
--- a/src/client/app/common/views/pages/page/page.vue
+++ b/src/client/app/common/views/components/page/page.vue
@@ -1,6 +1,6 @@
<template>
-<div v-if="page" class="iroscrza" :class="{ shadow: $store.state.device.useShadow, round: $store.state.device.roundedCorners, center: page.alignCenter }" :style="{ fontFamily: page.font }" :key="path">
- <header>
+<div class="iroscrza" :class="{ shadow: $store.state.device.useShadow, round: $store.state.device.roundedCorners, center: page.alignCenter }" :style="{ fontFamily: page.font }">
+ <header v-if="showTitle">
<div class="title">{{ page.title }}</div>
</header>
@@ -8,9 +8,13 @@
<x-block v-for="child in page.content" :value="child" @input="v => updateBlock(v)" :page="page" :script="script" :key="child.id" :h="2"/>
</div>
- <footer>
+ <footer v-if="showFooter">
<small>@{{ page.user.username }}</small>
- <router-link v-if="$store.getters.isSignedIn && $store.state.i.id === page.userId" :to="`/i/pages/edit/${page.id}`">{{ $t('edit-this-page') }}</router-link>
+ <template v-if="$store.getters.isSignedIn && $store.state.i.id === page.userId">
+ <router-link :to="`/i/pages/edit/${page.id}`">{{ $t('edit-this-page') }}</router-link>
+ <a v-if="$store.state.i.pinnedPageId === page.id" @click="pin(false)">{{ $t('unpin-this-page') }}</a>
+ <a v-else @click="pin(true)">{{ $t('pin-this-page') }}</a>
+ </template>
<router-link :to="`./${page.name}/view-source`">{{ $t('view-source') }}</router-link>
<div class="like">
<button @click="unlike()" v-if="page.isLiked" :title="$t('unlike')"><fa :icon="faHeartS"/></button>
@@ -25,7 +29,7 @@
import Vue from 'vue';
import i18n from '../../../../i18n';
import { faHeart as faHeartS } from '@fortawesome/free-solid-svg-icons';
-import { faHeart, faStickyNote } from '@fortawesome/free-regular-svg-icons';
+import { faHeart } from '@fortawesome/free-regular-svg-icons';
import XBlock from './page.block.vue';
import { ASEvaluator } from '../../../../../../misc/aiscript/evaluator';
import { collectPageVars } from '../../../scripts/collect-page-vars';
@@ -35,8 +39,10 @@ class Script {
public aiScript: ASEvaluator;
private onError: any;
public vars: Record<string, any>;
+ public page: Record<string, any>;
- constructor(aiScript, onError) {
+ constructor(page, aiScript, onError) {
+ this.page = page;
this.aiScript = aiScript;
this.onError = onError;
this.eval();
@@ -67,64 +73,43 @@ export default Vue.extend({
},
props: {
- pageName: {
- type: String,
+ page: {
+ type: Object,
required: true
},
- username: {
- type: String,
- required: true
+ showTitle: {
+ type: Boolean,
+ required: false,
+ default: true
+ },
+ showFooter: {
+ type: Boolean,
+ required: false,
+ default: false
},
},
data() {
return {
- page: null,
script: null,
faHeartS, faHeart
};
},
- computed: {
- path(): string {
- return this.username + '/' + this.pageName;
- }
- },
-
- watch: {
- path() {
- this.fetch();
- }
- },
-
created() {
- this.fetch();
+ const pageVars = this.getPageVars();
+ this.script = new Script(this.page, new ASEvaluator(this.page.variables, pageVars, {
+ randomSeed: Math.random(),
+ user: this.page.user,
+ visitor: this.$store.state.i,
+ page: this.page,
+ url: url
+ }), e => {
+ console.dir(e);
+ });
},
methods: {
- fetch() {
- this.$root.api('pages/show', {
- name: this.pageName,
- username: this.username,
- }).then(page => {
- this.page = page;
- this.$emit('init', {
- title: this.page.title,
- icon: faStickyNote
- });
- const pageVars = this.getPageVars();
- this.script = new Script(new ASEvaluator(this.page.variables, pageVars, {
- randomSeed: Math.random(),
- user: page.user,
- visitor: this.$store.state.i,
- page: page,
- url: url
- }), e => {
- console.dir(e);
- });
- });
- },
-
getPageVars() {
return collectPageVars(this.page.content);
},
@@ -145,6 +130,17 @@ export default Vue.extend({
this.page.isLiked = false;
this.page.likedCount--;
});
+ },
+
+ pin(pin) {
+ this.$root.api('i/update', {
+ pinnedPageId: pin ? this.page.id : null,
+ }).then(() => {
+ this.$root.dialog({
+ type: 'success',
+ splash: true
+ });
+ });
}
}
});
diff --git a/src/client/app/common/views/components/poll.vue b/src/client/app/common/views/components/poll.vue
index dc3aaa34f3..bd5eeaf832 100644
--- a/src/client/app/common/views/components/poll.vue
+++ b/src/client/app/common/views/components/poll.vue
@@ -5,7 +5,7 @@
<div class="backdrop" :style="{ 'width': `${showResult ? (choice.votes / total * 100) : 0}%` }"></div>
<span>
<template v-if="choice.isVoted"><fa icon="check"/></template>
- <mfm :text="choice.text" :should-break="false" :plain-text="true" :custom-emojis="note.emojis"/>
+ <mfm :text="choice.text" :plain="true" :custom-emojis="note.emojis"/>
<span class="votes" v-if="showResult">({{ $t('vote-count').replace('{}', choice.votes) }})</span>
</span>
</li>
diff --git a/src/client/app/common/views/components/settings/2fa.vue b/src/client/app/common/views/components/settings/2fa.vue
index eb645898e2..813a91b5c0 100644
--- a/src/client/app/common/views/components/settings/2fa.vue
+++ b/src/client/app/common/views/components/settings/2fa.vue
@@ -28,6 +28,10 @@
</div>
</div>
+ <ui-switch v-model="usePasswordLessLogin" @change="updatePasswordLessLogin" v-if="$store.state.i.securityKeysList.length > 0">
+ {{ $t('use-password-less-login') }}
+ </ui-switch>
+
<ui-info warn v-if="registration && registration.error">{{ $t('something-went-wrong') }} {{ registration.error }}</ui-info>
<ui-button v-if="!registration || registration.error" @click="addSecurityKey">{{ $t('register') }}</ui-button>
@@ -80,6 +84,7 @@ export default Vue.extend({
return {
data: null,
supportsCredentials: !!navigator.credentials,
+ usePasswordLessLogin: this.$store.state.i.usePasswordLessLogin,
registration: null,
keyName: '',
token: null
@@ -113,6 +118,9 @@ export default Vue.extend({
this.$root.api('i/2fa/unregister', {
password: password
}).then(() => {
+ this.usePasswordLessLogin = false;
+ this.updatePasswordLessLogin();
+ }).then(() => {
this.$notify(this.$t('unregistered'));
this.$store.state.i.twoFactorEnabled = false;
});
@@ -158,6 +166,9 @@ export default Vue.extend({
password,
credentialId: key.id
}).then(() => {
+ this.usePasswordLessLogin = false;
+ this.updatePasswordLessLogin();
+ }).then(() => {
this.$notify(this.$t('key-unregistered'));
});
});
@@ -213,6 +224,11 @@ export default Vue.extend({
this.registration.stage = -1;
});
});
+ },
+ updatePasswordLessLogin() {
+ this.$root.api('i/2fa/password-less', {
+ value: !!this.usePasswordLessLogin
+ });
}
}
});
diff --git a/src/client/app/common/views/components/settings/app-type.vue b/src/client/app/common/views/components/settings/app-type.vue
new file mode 100644
index 0000000000..90ff28803b
--- /dev/null
+++ b/src/client/app/common/views/components/settings/app-type.vue
@@ -0,0 +1,36 @@
+<template>
+<ui-card>
+ <template #title><fa :icon="faMobileAlt"/> {{ $t('title') }}</template>
+
+ <section class="fit-top">
+ <p>{{ $t('intro') }}</p>
+ <ui-select v-model="appTypeForce" :placeholder="$t('intro')">
+ <option v-for="x in ['auto', 'desktop', 'mobile']" :value="x" :key="x">{{ $t(`choices.${x}`) }}</option>
+ </ui-select>
+ <ui-info warn>{{ $t('info') }}</ui-info>
+ </section>
+</ui-card>
+</template>
+
+<script lang="ts">
+import Vue from 'vue';
+import i18n from '../../../../i18n';
+import { faMobileAlt } from '@fortawesome/free-solid-svg-icons'
+
+export default Vue.extend({
+ i18n: i18n('common/views/components/settings/app-type.vue'),
+
+ data() {
+ return {
+ faMobileAlt
+ };
+ },
+
+ computed: {
+ appTypeForce: {
+ get() { return this.$store.state.device.appTypeForce; },
+ set(value) { this.$store.commit('device/set', { key: 'appTypeForce', value }); }
+ },
+ },
+});
+</script>
diff --git a/src/client/app/common/views/components/settings/drive.vue b/src/client/app/common/views/components/settings/drive.vue
index 7bdc806ae7..da028e85ef 100644
--- a/src/client/app/common/views/components/settings/drive.vue
+++ b/src/client/app/common/views/components/settings/drive.vue
@@ -11,6 +11,12 @@
<header>{{ $t('stats') }}</header>
<div ref="chart" style="margin-bottom: -16px; margin-left: -8px; color: #000;"></div>
</section>
+
+ <section>
+ <header>{{ $t('default-upload-folder') }}</header>
+ <ui-input v-model="uploadFolderName" readonly>{{ $t('default-upload-folder-name') }}</ui-input>
+ <ui-button @click="chooseUploadFolder()">{{ $t('change-default-upload-folder') }}</ui-button>
+ </section>
</ui-card>
</template>
@@ -26,7 +32,8 @@ export default Vue.extend({
return {
fetching: true,
usage: null,
- capacity: null
+ capacity: null,
+ uploadFolderName: null
};
},
@@ -40,10 +47,25 @@ export default Vue.extend({
l: 0.5
})
};
- }
+ },
+
+ uploadFolder: {
+ get() { return this.$store.state.settings.uploadFolder; },
+ set(value) { this.$store.dispatch('settings/set', { key: 'uploadFolder', value }); }
+ },
},
mounted() {
+ if (this.uploadFolder == null) {
+ this.uploadFolderName = this.$t('@._settings.root');
+ } else {
+ this.$root.api('drive/folders/show', {
+ folderId: this.uploadFolder
+ }).then(folder => {
+ this.uploadFolderName = folder.name;
+ });
+ }
+
this.$root.api('drive').then(info => {
this.capacity = info.capacity;
this.usage = info.usage;
@@ -89,6 +111,9 @@ export default Vue.extend({
height: 150,
zoom: {
enabled: false
+ },
+ toolbar: {
+ show: false
}
},
plotOptions: {
@@ -152,6 +177,13 @@ export default Vue.extend({
chart.render();
});
+ },
+
+ chooseUploadFolder() {
+ this.$chooseDriveFolder().then(folder => {
+ this.uploadFolder = folder ? folder.id : null;
+ this.uploadFolderName = folder ? folder.name : this.$t('@._settings.root');
+ })
}
}
});
diff --git a/src/client/app/common/views/components/settings/settings.vue b/src/client/app/common/views/components/settings/settings.vue
index 1254eb5e5e..281524979e 100644
--- a/src/client/app/common/views/components/settings/settings.vue
+++ b/src/client/app/common/views/components/settings/settings.vue
@@ -140,7 +140,19 @@
<section>
<header>{{ $t('@._settings.web-search-engine') }}</header>
- <ui-input v-model="webSearchEngine">{{ $t('@._settings.web-search-engine') }}<template #desc>{{ $t('@._settings.web-search-engine-desc') }}</template></ui-input>
+ <ui-input v-model="webSearchEngine">{{ $t('@._settings.web-search-engine') }}
+ <template #desc>{{ $t('@._settings.web-search-engine-desc') }}</template>
+ </ui-input>
+ </section>
+
+ <section v-if="!$root.isMobile">
+ <header>{{ $t('@._settings.paste') }}</header>
+ <ui-input v-model="pastedFileName">{{ $t('@._settings.pasted-file-name') }}
+ <template #desc>{{ $t('@._settings.pasted-file-name-desc') }}</template>
+ </ui-input>
+ <ui-switch v-model="pasteDialog">{{ $t('@._settings.paste-dialog') }}
+ <template #desc>{{ $t('@._settings.paste-dialog-desc') }}</template>
+ </ui-switch>
</section>
</ui-card>
@@ -163,6 +175,7 @@
</ui-card>
<x-language/>
+ <x-app-type/>
</template>
<template v-if="page == null || page == 'notification'">
@@ -271,6 +284,7 @@ import XPassword from './password.vue';
import XProfile from './profile.vue';
import XApi from './api.vue';
import XLanguage from './language.vue';
+import XAppType from './app-type.vue';
import XNotification from './notification.vue';
import { url, version } from '../../../../config';
@@ -291,6 +305,7 @@ export default Vue.extend({
XProfile,
XApi,
XLanguage,
+ XAppType,
XNotification,
},
props: {
@@ -409,6 +424,16 @@ export default Vue.extend({
set(value) { this.$store.dispatch('settings/set', { key: 'webSearchEngine', value }); }
},
+ pastedFileName: {
+ get() { return this.$store.state.settings.pastedFileName; },
+ set(value) { this.$store.dispatch('settings/set', { key: 'pastedFileName', value }); }
+ },
+
+ pasteDialog: {
+ get() { return this.$store.state.settings.pasteDialog; },
+ set(value) { this.$store.dispatch('settings/set', { key: 'pasteDialog', value }); }
+ },
+
showReplyTarget: {
get() { return this.$store.state.settings.showReplyTarget; },
set(value) { this.$store.dispatch('settings/set', { key: 'showReplyTarget', value }); }
diff --git a/src/client/app/common/views/components/signin.vue b/src/client/app/common/views/components/signin.vue
index 8498a1dc3e..f76f989d6d 100644
--- a/src/client/app/common/views/components/signin.vue
+++ b/src/client/app/common/views/components/signin.vue
@@ -7,7 +7,7 @@
<template #prefix>@</template>
<template #suffix>@{{ host }}</template>
</ui-input>
- <ui-input v-model="password" type="password" :with-password-toggle="true" required>
+ <ui-input v-model="password" type="password" :with-password-toggle="true" v-if="!user || user && !user.usePasswordLessLogin" required>
<span>{{ $t('password') }}</span>
<template #prefix><fa icon="lock"/></template>
</ui-input>
@@ -28,6 +28,10 @@
</div>
<div class="twofa-group totp-group">
<p style="margin-bottom:0;">{{ $t('enter-2fa-code') }}</p>
+ <ui-input v-model="password" type="password" :with-password-toggle="true" v-if="user && user.usePasswordLessLogin" required>
+ <span>{{ $t('password') }}</span>
+ <template #prefix><fa icon="lock"/></template>
+ </ui-input>
<ui-input v-model="token" type="text" pattern="^[0-9]{6}$" autocomplete="off" spellcheck="false" required>
<span>{{ $t('@.2fa') }}</span>
<template #prefix><fa icon="gavel"/></template>
diff --git a/src/client/app/common/views/components/uploader.vue b/src/client/app/common/views/components/uploader.vue
index 78fbcbf6b8..9f02da6c1e 100644
--- a/src/client/app/common/views/components/uploader.vue
+++ b/src/client/app/common/views/components/uploader.vue
@@ -46,7 +46,7 @@ export default Vue.extend({
});
},
- upload(file: File, folder: any) {
+ upload(file: File, folder: any, name?: string) {
if (folder && typeof folder == 'object') folder = folder.id;
const id = Math.random();
@@ -61,7 +61,7 @@ export default Vue.extend({
const ctx = {
id: id,
- name: file.name || 'untitled',
+ name: name || file.name || 'untitled',
progress: undefined,
img: window.URL.createObjectURL(file)
};
@@ -75,6 +75,7 @@ export default Vue.extend({
data.append('file', file);
if (folder) data.append('folderId', folder);
+ if (name) data.append('name', name);
const xhr = new XMLHttpRequest();
xhr.open('POST', apiUrl + '/drive/files/create', true);
diff --git a/src/client/app/common/views/components/url-preview.vue b/src/client/app/common/views/components/url-preview.vue
index 20fbcbb046..476c671e77 100644
--- a/src/client/app/common/views/components/url-preview.vue
+++ b/src/client/app/common/views/components/url-preview.vue
@@ -63,6 +63,7 @@ export default Vue.extend({
data() {
const isSelf = this.url.startsWith(local);
const hasRoute =
+ (this.url.substr(local.length) === '/') ||
this.url.substr(local.length).startsWith('/@') ||
this.url.substr(local.length).startsWith('/notes/') ||
this.url.substr(local.length).startsWith('/pages/');
diff --git a/src/client/app/common/views/components/user-list.vue b/src/client/app/common/views/components/user-list.vue
index 466be41506..69cb65b445 100644
--- a/src/client/app/common/views/components/user-list.vue
+++ b/src/client/app/common/views/components/user-list.vue
@@ -16,7 +16,7 @@
<p class="username">@{{ user | acct }}</p>
</div>
<div class="description" v-if="user.description" :title="user.description">
- <mfm :text="user.description" :is-note="false" :author="user" :i="$store.state.i" :custom-emojis="user.emojis" :should-break="false" :plain-text="true"/>
+ <mfm :text="user.description" :is-note="false" :author="user" :i="$store.state.i" :custom-emojis="user.emojis" :plain="true" :nowrap="true"/>
</div>
<mk-follow-button class="follow-button" v-if="$store.getters.isSignedIn && user.id != $store.state.i.id" :user="user" mini/>
</div>
diff --git a/src/client/app/common/views/components/user-name.vue b/src/client/app/common/views/components/user-name.vue
index 3959193eb4..6aca36acbd 100644
--- a/src/client/app/common/views/components/user-name.vue
+++ b/src/client/app/common/views/components/user-name.vue
@@ -1,5 +1,5 @@
<template>
-<mfm :text="user.name || user.username" :should-break="false" :plain-text="true" :custom-emojis="user.emojis"/>
+<mfm :text="user.name || user.username" :plain="true" :nowrap="true" :custom-emojis="user.emojis"/>
</template>
<script lang="ts">
diff --git a/src/client/app/common/views/deck/deck.notification.vue b/src/client/app/common/views/deck/deck.notification.vue
index 27a2dffef5..e1d9669002 100644
--- a/src/client/app/common/views/deck/deck.notification.vue
+++ b/src/client/app/common/views/deck/deck.notification.vue
@@ -12,7 +12,7 @@
</header>
<router-link class="note-ref" :to="notification.note | notePage" :title="getNoteSummary(notification.note)">
<fa icon="quote-left"/>
- <mfm :text="getNoteSummary(notification.note)" :should-break="false" :plain-text="true" :custom-emojis="notification.note.emojis"/>
+ <mfm :text="getNoteSummary(notification.note)" :plain="true" :nowrap="true" :custom-emojis="notification.note.emojis"/>
<fa icon="quote-right"/>
</router-link>
</div>
@@ -30,7 +30,7 @@
</header>
<router-link class="note-ref" :to="notification.note | notePage" :title="getNoteSummary(notification.note.renote)">
<fa icon="quote-left"/>
- <mfm :text="getNoteSummary(notification.note.renote)" :should-break="false" :plain-text="true" :custom-emojis="notification.note.renote.emojis"/>
+ <mfm :text="getNoteSummary(notification.note.renote)" :plain="true" :nowrap="true" :custom-emojis="notification.note.renote.emojis"/>
<fa icon="quote-right"/>
</router-link>
</div>
@@ -74,7 +74,7 @@
</header>
<router-link class="note-ref" :to="notification.note | notePage" :title="getNoteSummary(notification.note)">
<fa icon="quote-left"/>
- <mfm :text="getNoteSummary(notification.note)" :should-break="false" :plain-text="true" :custom-emojis="notification.note.emojis"/>
+ <mfm :text="getNoteSummary(notification.note)" :plain="true" :nowrap="true" :custom-emojis="notification.note.emojis"/>
<fa icon="quote-right"/>
</router-link>
</div>
diff --git a/src/client/app/common/views/deck/deck.page-column.vue b/src/client/app/common/views/deck/deck.page-column.vue
new file mode 100644
index 0000000000..0ef391a51d
--- /dev/null
+++ b/src/client/app/common/views/deck/deck.page-column.vue
@@ -0,0 +1,69 @@
+<template>
+<x-column>
+ <template #header>
+ <fa :icon="faStickyNote"/>{{ page ? page.name : '' }}
+ </template>
+
+ <div v-if="page">
+ <x-page :page="page" :key="page.id"/>
+ </div>
+</x-column>
+</template>
+
+<script lang="ts">
+import Vue from 'vue';
+import { faStickyNote } from '@fortawesome/free-regular-svg-icons';
+import i18n from '../../../i18n';
+import XColumn from './deck.column.vue';
+import XPage from '../../../common/views/components/page/page.vue';
+
+export default Vue.extend({
+ i18n: i18n(),
+
+ components: {
+ XColumn,
+ XPage
+ },
+
+ props: {
+ pageName: {
+ type: String,
+ required: true
+ },
+ username: {
+ type: String,
+ required: true
+ },
+ },
+
+ data() {
+ return {
+ page: null,
+ faStickyNote
+ };
+ },
+
+ watch: {
+ $route: 'fetch'
+ },
+
+ created() {
+ this.fetch();
+ },
+
+ methods: {
+ fetch() {
+ this.$root.api('pages/show', {
+ name: this.pageName,
+ username: this.username,
+ }).then(page => {
+ this.page = page;
+ this.$emit('init', {
+ title: this.page.title,
+ icon: faStickyNote
+ });
+ });
+ }
+ }
+});
+</script>
diff --git a/src/client/app/common/views/deck/deck.user-column.home.vue b/src/client/app/common/views/deck/deck.user-column.home.vue
index 56b117a7dd..9fb50a6672 100644
--- a/src/client/app/common/views/deck/deck.user-column.home.vue
+++ b/src/client/app/common/views/deck/deck.user-column.home.vue
@@ -1,5 +1,11 @@
<template>
<div>
+ <ui-container v-if="user.pinnedPage" :body-togglable="true">
+ <template #header><fa icon="thumbtack"/> {{ $t('pinned-page') }}</template>
+ <div>
+ <x-page :page="user.pinnedPage" :key="user.pinnedPage.id" :show-title="!user.pinnedPage.hideTitleWhenPinned"/>
+ </div>
+ </ui-container>
<ui-container v-if="user.pinnedNotes && user.pinnedNotes.length > 0" :body-togglable="true">
<template #header><fa icon="thumbtack"/> {{ $t('pinned-notes') }}</template>
<div>
@@ -48,6 +54,7 @@ export default Vue.extend({
components: {
XNotes,
+ XPage: () => import('../../../common/views/components/page/page.vue').then(m => m.default),
},
props: {
diff --git a/src/client/app/common/views/deck/deck.user-column.vue b/src/client/app/common/views/deck/deck.user-column.vue
index c508f3f69f..8ab61f2047 100644
--- a/src/client/app/common/views/deck/deck.user-column.vue
+++ b/src/client/app/common/views/deck/deck.user-column.vue
@@ -30,7 +30,7 @@
<div class="fields" v-if="user.fields">
<dl class="field" v-for="(field, i) in user.fields" :key="i">
<dt class="name">
- <mfm :text="field.name" :should-break="false" :plain-text="true" :custom-emojis="user.emojis"/>
+ <mfm :text="field.name" :plain="true" :custom-emojis="user.emojis"/>
</dt>
<dd class="value">
<mfm :text="field.value" :author="user" :i="$store.state.i" :custom-emojis="user.emojis"/>
diff --git a/src/client/app/common/views/pages/follow.vue b/src/client/app/common/views/pages/follow.vue
index f6a11a7b4f..f08ddf2642 100644
--- a/src/client/app/common/views/pages/follow.vue
+++ b/src/client/app/common/views/pages/follow.vue
@@ -1,7 +1,7 @@
<template>
<div class="syxhndwprovvuqhmyvveewmbqayniwkv" v-if="!fetching">
<div class="signed-in-as">
- <mfm :text="$t('signed-in-as').replace('{}', myName)" :should-break="false" :plain-text="true" :custom-emojis="$store.state.i.emojis"/>
+ <mfm :text="$t('signed-in-as').replace('{}', myName)" :plain="true" :custom-emojis="$store.state.i.emojis"/>
</div>
<main>
<div class="banner" :style="bannerStyle"></div>
diff --git a/src/client/app/common/views/pages/page-editor/els/page-editor.el.button.vue b/src/client/app/common/views/pages/page-editor/els/page-editor.el.button.vue
index f89279f05a..6a82b0eec9 100644
--- a/src/client/app/common/views/pages/page-editor/els/page-editor.el.button.vue
+++ b/src/client/app/common/views/pages/page-editor/els/page-editor.el.button.vue
@@ -4,12 +4,31 @@
<section class="xfhsjczc">
<ui-input v-model="value.text"><span>{{ $t('blocks._button.text') }}</span></ui-input>
+ <ui-switch v-model="value.primary"><span>{{ $t('blocks._button.colored') }}</span></ui-switch>
<ui-select v-model="value.action">
<template #label>{{ $t('blocks._button.action') }}</template>
<option value="dialog">{{ $t('blocks._button._action.dialog') }}</option>
<option value="resetRandom">{{ $t('blocks._button._action.resetRandom') }}</option>
+ <option value="pushEvent">{{ $t('blocks._button._action.pushEvent') }}</option>
</ui-select>
- <ui-input v-if="value.action === 'dialog'" v-model="value.content"><span>{{ $t('blocks._button._action._dialog.content') }}</span></ui-input>
+ <template v-if="value.action === 'dialog'">
+ <ui-input v-model="value.content"><span>{{ $t('blocks._button._action._dialog.content') }}</span></ui-input>
+ </template>
+ <template v-else-if="value.action === 'pushEvent'">
+ <ui-input v-model="value.event"><span>{{ $t('blocks._button._action._pushEvent.event') }}</span></ui-input>
+ <ui-input v-model="value.message"><span>{{ $t('blocks._button._action._pushEvent.message') }}</span></ui-input>
+ <ui-select v-model="value.var">
+ <template #label>{{ $t('blocks._button._action._pushEvent.variable') }}</template>
+ <option :value="null">{{ $t('blocks._button._action._pushEvent.no-variable') }}</option>
+ <option v-for="v in aiScript.getVarsByType()" :value="v.name">{{ v.name }}</option>
+ <optgroup :label="$t('script.pageVariables')">
+ <option v-for="v in aiScript.getPageVarsByType()" :value="v">{{ v }}</option>
+ </optgroup>
+ <optgroup :label="$t('script.enviromentVariables')">
+ <option v-for="v in aiScript.getEnvVarsByType()" :value="v">{{ v }}</option>
+ </optgroup>
+ </ui-select>
+ </template>
</section>
</x-container>
</template>
@@ -31,6 +50,9 @@ export default Vue.extend({
value: {
required: true
},
+ aiScript: {
+ required: true,
+ },
},
data() {
@@ -43,6 +65,10 @@ export default Vue.extend({
if (this.value.text == null) Vue.set(this.value, 'text', '');
if (this.value.action == null) Vue.set(this.value, 'action', 'dialog');
if (this.value.content == null) Vue.set(this.value, 'content', null);
+ if (this.value.event == null) Vue.set(this.value, 'event', null);
+ if (this.value.message == null) Vue.set(this.value, 'message', null);
+ if (this.value.primary == null) Vue.set(this.value, 'primary', false);
+ if (this.value.var == null) Vue.set(this.value, 'var', null);
},
});
</script>
diff --git a/src/client/app/common/views/pages/page-editor/page-editor.vue b/src/client/app/common/views/pages/page-editor/page-editor.vue
index ebe0f4688d..ade7d86991 100644
--- a/src/client/app/common/views/pages/page-editor/page-editor.vue
+++ b/src/client/app/common/views/pages/page-editor/page-editor.vue
@@ -35,6 +35,8 @@
<option value="sans-serif">{{ $t('fontSansSerif') }}</option>
</ui-select>
+ <ui-switch v-model="hideTitleWhenPinned">{{ $t('hide-title-when-pinned') }}</ui-switch>
+
<div class="eyeCatch">
<ui-button v-if="eyeCatchingImageId == null && !readonly" @click="setEyeCatchingImage()"><fa :icon="faPlus"/> {{ $t('set-eye-catching-image') }}</ui-button>
<div v-else-if="eyeCatchingImage">
@@ -140,6 +142,7 @@ export default Vue.extend({
font: 'sans-serif',
content: [],
alignCenter: false,
+ hideTitleWhenPinned: false,
variables: [],
aiScript: null,
showOptions: false,
@@ -192,6 +195,7 @@ export default Vue.extend({
this.currentName = this.page.name;
this.summary = this.page.summary;
this.font = this.page.font;
+ this.hideTitleWhenPinned = this.page.hideTitleWhenPinned;
this.alignCenter = this.page.alignCenter;
this.content = this.page.content;
this.variables = this.page.variables;
@@ -223,6 +227,7 @@ export default Vue.extend({
name: this.name.trim(),
summary: this.summary,
font: this.font,
+ hideTitleWhenPinned: this.hideTitleWhenPinned,
alignCenter: this.alignCenter,
content: this.content,
variables: this.variables,
@@ -240,6 +245,7 @@ export default Vue.extend({
name: this.name.trim(),
summary: this.summary,
font: this.font,
+ hideTitleWhenPinned: this.hideTitleWhenPinned,
alignCenter: this.alignCenter,
content: this.content,
variables: this.variables,
diff --git a/src/client/app/common/views/pages/page.vue b/src/client/app/common/views/pages/page.vue
new file mode 100644
index 0000000000..d1c4c2be43
--- /dev/null
+++ b/src/client/app/common/views/pages/page.vue
@@ -0,0 +1,63 @@
+<template>
+<x-page v-if="page" :page="page" :key="page.id" :show-footer="true"/>
+</template>
+
+<script lang="ts">
+import Vue from 'vue';
+import { faStickyNote } from '@fortawesome/free-regular-svg-icons';
+import XPage from '../components/page/page.vue';
+
+export default Vue.extend({
+ components: {
+ XPage
+ },
+
+ props: {
+ pageName: {
+ type: String,
+ required: true
+ },
+ username: {
+ type: String,
+ required: true
+ },
+ },
+
+ data() {
+ return {
+ page: null,
+ };
+ },
+
+ computed: {
+ path(): string {
+ return this.username + '/' + this.pageName;
+ }
+ },
+
+ watch: {
+ path() {
+ this.fetch();
+ }
+ },
+
+ created() {
+ this.fetch();
+ },
+
+ methods: {
+ fetch() {
+ this.$root.api('pages/show', {
+ name: this.pageName,
+ username: this.username,
+ }).then(page => {
+ this.page = page;
+ this.$emit('init', {
+ title: this.page.title,
+ icon: faStickyNote
+ });
+ });
+ },
+ }
+});
+</script>
diff --git a/src/client/app/common/views/widgets/post-form.vue b/src/client/app/common/views/widgets/post-form.vue
index e180290f95..6680a11435 100644
--- a/src/client/app/common/views/widgets/post-form.vue
+++ b/src/client/app/common/views/widgets/post-form.vue
@@ -38,6 +38,7 @@
import define from '../../../common/define-widget';
import i18n from '../../../i18n';
import insertTextAtCursor from 'insert-text-at-cursor';
+import { formatTimeString } from '../../../../../misc/format-time-string';
export default define({
name: 'post-form',
@@ -109,10 +110,23 @@ export default define({
if ((e.which == 10 || e.which == 13) && (e.ctrlKey || e.metaKey) && !this.posting && this.text) this.post();
},
- onPaste(e) {
- for (const item of Array.from(e.clipboardData.items)) {
+ async onPaste(e: ClipboardEvent) {
+ for (const { item, i } of Array.from(e.clipboardData.items).map((item, i) => ({item, i}))) {
if (item.kind == 'file') {
- this.upload(item.getAsFile());
+ const file = item.getAsFile();
+ const lio = file.name.lastIndexOf('.');
+ const ext = lio >= 0 ? file.name.slice(lio) : '';
+ const formatted = `${formatTimeString(new Date(file.lastModified), this.$store.state.settings.pastedFileName).replace(/{{number}}/g, `${i + 1}`)}${ext}`;
+ const name = this.$store.state.settings.pasteDialog
+ ? await this.$root.dialog({
+ title: this.$t('@.post-form.enter-file-name'),
+ input: {
+ default: formatted
+ },
+ allowEmpty: false
+ }).then(({ canceled, result }) => canceled ? false : result)
+ : formatted;
+ if (name) this.upload(file, name);
}
}
},
@@ -121,8 +135,8 @@ export default define({
for (const x of Array.from((this.$refs.file as any).files)) this.upload(x);
},
- upload(file) {
- (this.$refs.uploader as any).upload(file);
+ upload(file: File, name?: string) {
+ (this.$refs.uploader as any).upload(file, this.$store.state.settings.uploadFolder, name);
},
onDragover(e) {
diff --git a/src/client/app/desktop/script.ts b/src/client/app/desktop/script.ts
index 8065241714..1a4be33020 100644
--- a/src/client/app/desktop/script.ts
+++ b/src/client/app/desktop/script.ts
@@ -148,6 +148,7 @@ init(async (launch, os) => {
{ path: '/i/groups', component: DeckColumn, props: route => ({ component: () => import('../common/views/pages/user-groups.vue').then(m => m.default) }) },
{ path: '/i/groups/:groupId', component: DeckColumn, props: route => ({ component: () => import('../common/views/pages/user-group-editor.vue').then(m => m.default), groupId: route.params.groupId }) },
{ path: '/i/follow-requests', component: DeckColumn, props: route => ({ component: () => import('../common/views/pages/follow-requests.vue').then(m => m.default) }) },
+ { path: '/@:username/pages/:pageName', name: 'page', props: true, component: () => import('../common/views/deck/deck.page-column.vue').then(m => m.default) },
]}
: { path: '/', component: MkHome, children: [
{ path: '', name: 'index', component: MkHomeTimeline },
@@ -171,12 +172,11 @@ init(async (launch, os) => {
{ path: '/i/follow-requests', component: () => import('../common/views/pages/follow-requests.vue').then(m => m.default) },
{ path: '/i/pages/new', component: () => import('../common/views/pages/page-editor/page-editor.vue').then(m => m.default) },
{ path: '/i/pages/edit/:pageId', component: () => import('../common/views/pages/page-editor/page-editor.vue').then(m => m.default), props: route => ({ initPageId: route.params.pageId }) },
- { path: '/@:user/pages/:page', component: () => import('../common/views/pages/page/page.vue').then(m => m.default), props: route => ({ pageName: route.params.page, username: route.params.user }) },
+ { path: '/@:user/pages/:page', component: () => import('../common/views/pages/page.vue').then(m => m.default), props: route => ({ pageName: route.params.page, username: route.params.user }) },
{ path: '/@:user/pages/:pageName/view-source', component: () => import('../common/views/pages/page-editor/page-editor.vue').then(m => m.default), props: route => ({ initUser: route.params.user, initPageName: route.params.pageName }) },
]},
{ path: '/i/pages/new', component: () => import('../common/views/pages/page-editor/page-editor.vue').then(m => m.default) },
{ path: '/i/pages/edit/:pageId', component: () => import('../common/views/pages/page-editor/page-editor.vue').then(m => m.default), props: route => ({ initPageId: route.params.pageId }) },
- { path: '/@:user/pages/:page', component: () => import('../common/views/pages/page/page.vue').then(m => m.default), props: route => ({ pageName: route.params.page, username: route.params.user }) },
{ path: '/@:user/pages/:pageName/view-source', component: () => import('../common/views/pages/page-editor/page-editor.vue').then(m => m.default), props: route => ({ initUser: route.params.user, initPageName: route.params.pageName }) },
{ path: '/i/messaging/group/:group', component: MkMessagingRoom },
{ path: '/i/messaging/:user', component: MkMessagingRoom },
diff --git a/src/client/app/desktop/views/components/drive.folder.vue b/src/client/app/desktop/views/components/drive.folder.vue
index fd6de5a05e..cf59d51b01 100644
--- a/src/client/app/desktop/views/components/drive.folder.vue
+++ b/src/client/app/desktop/views/components/drive.folder.vue
@@ -20,6 +20,9 @@
<template v-if="!hover"><fa :icon="['far', 'folder']" fixed-width/></template>
{{ folder.name }}
</p>
+ <p class="upload" v-if="$store.state.settings.uploadFolder == folder.id">
+ {{ $t('upload-folder') }}
+ </p>
</div>
</template>
@@ -73,6 +76,14 @@ export default Vue.extend({
text: this.$t('@.delete'),
icon: ['far', 'trash-alt'],
action: this.deleteFolder
+ }, null, {
+ type: 'nest',
+ text: this.$t('contextmenu.else-folders'),
+ menu: [{
+ type: 'item',
+ text: this.$t('contextmenu.set-as-upload-folder'),
+ action: this.setAsUploadFolder
+ }]
}], {
closed: () => {
this.isContextmenuShowing = false;
@@ -213,8 +224,37 @@ export default Vue.extend({
deleteFolder() {
this.$root.api('drive/folders/delete', {
folderId: this.folder.id
+ }).then(() => {
+ if (this.$store.state.settings.uploadFolder === this.folder.id) {
+ this.$store.dispatch('settings/set', {
+ key: 'uploadFolder',
+ value: null
+ });
+ }
+ }).catch(err => {
+ switch(err.id) {
+ case 'b0fc8a17-963c-405d-bfbc-859a487295e1':
+ this.$root.dialog({
+ type: 'error',
+ title: this.$t('unable-to-delete'),
+ text: this.$t('has-child-files-or-folders')
+ });
+ break;
+ default:
+ this.$root.dialog({
+ type: 'error',
+ text: this.$t('unable-to-delete')
+ });
+ }
});
- }
+ },
+
+ setAsUploadFolder() {
+ this.$store.dispatch('settings/set', {
+ key: 'uploadFolder',
+ value: this.folder.id
+ });
+ },
}
});
</script>
@@ -264,4 +304,10 @@ export default Vue.extend({
margin-left 2px
text-align left
+ > .upload
+ margin 4px 4px
+ font-size 0.8em
+ text-align right
+ color var(--desktopDriveFolderFg)
+
</style>
diff --git a/src/client/app/desktop/views/components/notifications.vue b/src/client/app/desktop/views/components/notifications.vue
index 6a8bc48ff2..b25f122e0e 100644
--- a/src/client/app/desktop/views/components/notifications.vue
+++ b/src/client/app/desktop/views/components/notifications.vue
@@ -24,7 +24,7 @@
</p>
<router-link class="note-ref" :to="notification.note | notePage" :title="getNoteSummary(notification.note)">
<fa icon="quote-left"/>
- <mfm :text="getNoteSummary(notification.note)" :should-break="false" :plain-text="true" :custom-emojis="notification.note.emojis"/>
+ <mfm :text="getNoteSummary(notification.note)" :plain="true" :nowrap="true" :custom-emojis="notification.note.emojis"/>
<fa icon="quote-right"/>
</router-link>
</div>
@@ -40,7 +40,7 @@
</p>
<router-link class="note-ref" :to="notification.note | notePage" :title="getNoteSummary(notification.note.renote)">
<fa icon="quote-left"/>
- <mfm :text="getNoteSummary(notification.note.renote)" :should-break="false" :plain-text="true" :custom-emojis="notification.note.renote.emojis"/>
+ <mfm :text="getNoteSummary(notification.note.renote)" :plain="true" :nowrap="true" :custom-emojis="notification.note.renote.emojis"/>
<fa icon="quote-right"/>
</router-link>
</div>
@@ -55,7 +55,7 @@
</router-link>
</p>
<router-link class="note-preview" :to="notification.note | notePage" :title="getNoteSummary(notification.note)">
- <mfm :text="getNoteSummary(notification.note)" :should-break="false" :plain-text="true" :custom-emojis="notification.note.emojis"/>
+ <mfm :text="getNoteSummary(notification.note)" :plain="true" :custom-emojis="notification.note.emojis"/>
</router-link>
</div>
</template>
@@ -91,7 +91,7 @@
</router-link>
</p>
<router-link class="note-preview" :to="notification.note | notePage" :title="getNoteSummary(notification.note)">
- <mfm :text="getNoteSummary(notification.note)" :should-break="false" :plain-text="true" :custom-emojis="notification.note.emojis"/>
+ <mfm :text="getNoteSummary(notification.note)" :plain="true" :custom-emojis="notification.note.emojis"/>
</router-link>
</div>
</template>
@@ -105,7 +105,7 @@
</router-link>
</p>
<router-link class="note-preview" :to="notification.note | notePage" :title="getNoteSummary(notification.note)">
- <mfm :text="getNoteSummary(notification.note)" :should-break="false" :plain-text="true" :custom-emojis="notification.note.emojis"/>
+ <mfm :text="getNoteSummary(notification.note)" :plain="true" :custom-emojis="notification.note.emojis"/>
</router-link>
</div>
</template>
@@ -118,7 +118,7 @@
</router-link></p>
<router-link class="note-ref" :to="notification.note | notePage" :title="getNoteSummary(notification.note)">
<fa icon="quote-left"/>
- <mfm :text="getNoteSummary(notification.note)" :should-break="false" :plain-text="true" :custom-emojis="notification.note.emojis"/>
+ <mfm :text="getNoteSummary(notification.note)" :plain="true" :nowrap="true" :custom-emojis="notification.note.emojis"/>
<fa icon="quote-right"/>
</router-link>
</div>
diff --git a/src/client/app/desktop/views/home/home.vue b/src/client/app/desktop/views/home/home.vue
index 3d05bee48d..527c2d52ef 100644
--- a/src/client/app/desktop/views/home/home.vue
+++ b/src/client/app/desktop/views/home/home.vue
@@ -62,7 +62,7 @@
</div>
</template>
<template v-else>
- <div v-for="place in ['left', 'right']" :class="place">
+ <div v-for="place in ['left', 'right']" :class="place" :key="place">
<component v-for="widget in widgets[place]" :is="`mkw-${widget.name}`" :key="widget.id" :ref="widget.id" :widget="widget" platform="desktop"/>
</div>
<div class="main">
@@ -392,7 +392,7 @@ export default Vue.extend({
margin 0 auto
&:not(.side)
- @media (max-width 1200px)
+ @media (max-width 1100px)
> *:not(.main)
display none
diff --git a/src/client/app/desktop/views/home/timeline.vue b/src/client/app/desktop/views/home/timeline.vue
index d8da6e4e26..b870395c18 100644
--- a/src/client/app/desktop/views/home/timeline.vue
+++ b/src/client/app/desktop/views/home/timeline.vue
@@ -4,12 +4,12 @@
<div class="main">
<component :is="src == 'list' ? 'mk-user-list-timeline' : 'x-core'" ref="tl" v-bind="options">
<header class="zahtxcqi">
- <span :data-active="src == 'home'" @click="src = 'home'"><fa icon="home"/> {{ $t('home') }}</span>
- <span :data-active="src == 'local'" @click="src = 'local'" v-if="enableLocalTimeline"><fa :icon="['far', 'comments']"/> {{ $t('local') }}</span>
- <span :data-active="src == 'hybrid'" @click="src = 'hybrid'" v-if="enableLocalTimeline"><fa icon="share-alt"/> {{ $t('hybrid') }}</span>
- <span :data-active="src == 'global'" @click="src = 'global'" v-if="enableGlobalTimeline"><fa icon="globe"/> {{ $t('global') }}</span>
- <span :data-active="src == 'tag'" @click="src = 'tag'" v-if="tagTl"><fa icon="hashtag"/> {{ tagTl.title }}</span>
- <span :data-active="src == 'list'" @click="src = 'list'" v-if="list"><fa icon="list"/> {{ list.name }}</span>
+ <div :data-active="src == 'home'" @click="src = 'home'"><fa icon="home"/> {{ $t('home') }}</div>
+ <div :data-active="src == 'local'" @click="src = 'local'" v-if="enableLocalTimeline"><fa :icon="['far', 'comments']"/> {{ $t('local') }}</div>
+ <div :data-active="src == 'hybrid'" @click="src = 'hybrid'" v-if="enableLocalTimeline"><fa icon="share-alt"/> {{ $t('hybrid') }}</div>
+ <div :data-active="src == 'global'" @click="src = 'global'" v-if="enableGlobalTimeline"><fa icon="globe"/> {{ $t('global') }}</div>
+ <div :data-active="src == 'tag'" @click="src = 'tag'" v-if="tagTl"><fa icon="hashtag"/> {{ tagTl.title }}</div>
+ <div :data-active="src == 'list'" @click="src = 'list'" v-if="list"><fa icon="list"/> {{ list.name }}</div>
<div class="buttons">
<button :data-active="src == 'mentions'" @click="src = 'mentions'" :title="$t('mentions')"><fa icon="at"/><i class="indicator" v-if="$store.state.i.hasUnreadMentions"><fa icon="circle"/></i></button>
<button :data-active="src == 'messages'" @click="src = 'messages'" :title="$t('messages')"><fa :icon="['far', 'envelope']"/><i class="indicator" v-if="$store.state.i.hasUnreadSpecifiedNotes"><fa icon="circle"/></i></button>
@@ -200,18 +200,19 @@ export default Vue.extend({
&.shadow
box-shadow 0 3px 8px rgba(0, 0, 0, 0.2)
- .zahtxcqi
+ header.zahtxcqi
+ display flex
+ flex-wrap wrap
padding 0 8px
z-index 10
background var(--faceHeader)
box-shadow 0 var(--lineWidth) var(--desktopTimelineHeaderShadow)
+ > *
+ flex-shrink 0
+
> .buttons
- position absolute
- z-index 2
- top 0
- right 0
- padding-right 8px
+ margin-left auto
> button
padding 0 8px
@@ -244,8 +245,7 @@ export default Vue.extend({
height 2px
background var(--primary)
- > span
- display inline-block
+ > div:not(.buttons)
padding 0 10px
line-height 42px
font-size 12px
diff --git a/src/client/app/desktop/views/home/user/user.header.vue b/src/client/app/desktop/views/home/user/user.header.vue
index 52a5165c3f..ca4ad0802c 100644
--- a/src/client/app/desktop/views/home/user/user.header.vue
+++ b/src/client/app/desktop/views/home/user/user.header.vue
@@ -28,7 +28,7 @@
<div class="fields" v-if="user.fields">
<dl class="field" v-for="(field, i) in user.fields" :key="i">
<dt class="name">
- <mfm :text="field.name" :should-break="false" :plain-text="true" :custom-emojis="user.emojis"/>
+ <mfm :text="field.name" :plain="true" :custom-emojis="user.emojis"/>
</dt>
<dd class="value">
<mfm :text="field.value" :author="user" :i="$store.state.i" :custom-emojis="user.emojis"/>
diff --git a/src/client/app/desktop/views/home/user/user.home.vue b/src/client/app/desktop/views/home/user/user.home.vue
index ec533efd3e..c47e0a0771 100644
--- a/src/client/app/desktop/views/home/user/user.home.vue
+++ b/src/client/app/desktop/views/home/user/user.home.vue
@@ -1,5 +1,6 @@
<template>
<div class="lnctpgve">
+ <x-page v-if="user.pinnedPage" :page="user.pinnedPage" :key="user.pinnedPage.id" :show-title="!user.pinnedPage.hideTitleWhenPinned"/>
<mk-note-detail v-for="n in user.pinnedNotes" :key="n.id" :note="n" :compact="true"/>
<!--<mk-calendar @chosen="warp" :start="new Date(user.createdAt)"/>-->
<div class="activity">
@@ -21,13 +22,15 @@ import i18n from '../../../../i18n';
import XTimeline from './user.timeline.vue';
import XPhotos from './user.photos.vue';
import XActivity from '../../../../common/views/components/activity.vue';
+import XPage from '../../../../common/views/components/page/page.vue';
export default Vue.extend({
i18n: i18n(),
components: {
XTimeline,
XPhotos,
- XActivity
+ XActivity,
+ XPage,
},
props: {
user: {
diff --git a/src/client/app/desktop/views/widgets/profile.vue b/src/client/app/desktop/views/widgets/profile.vue
index 57a604ff49..bad1925f69 100644
--- a/src/client/app/desktop/views/widgets/profile.vue
+++ b/src/client/app/desktop/views/widgets/profile.vue
@@ -118,6 +118,8 @@ export default define({
line-height 16px
font-weight bold
color var(--text)
+ overflow hidden
+ text-overflow ellipsis
> .username
display block
diff --git a/src/client/app/mobile/script.ts b/src/client/app/mobile/script.ts
index d04662cc1f..6222409931 100644
--- a/src/client/app/mobile/script.ts
+++ b/src/client/app/mobile/script.ts
@@ -129,6 +129,7 @@ init((launch, os) => {
{ path: '/i/groups', component: DeckColumn, props: route => ({ component: () => import('../common/views/pages/user-groups.vue').then(m => m.default) }) },
{ path: '/i/groups/:groupId', component: DeckColumn, props: route => ({ component: () => import('../common/views/pages/user-group-editor.vue').then(m => m.default), groupId: route.params.groupId }) },
{ path: '/i/follow-requests', component: DeckColumn, props: route => ({ component: () => import('../common/views/pages/follow-requests.vue').then(m => m.default) }) },
+ { path: '/@:username/pages/:pageName', name: 'page', props: true, component: () => import('../common/views/deck/deck.page-column.vue').then(m => m.default) },
]}]
: [
{ path: '/', name: 'index', component: MkIndex },
@@ -163,7 +164,7 @@ init((launch, os) => {
{ path: 'following', component: () => import('../common/views/pages/following.vue').then(m => m.default) },
{ path: 'followers', component: () => import('../common/views/pages/followers.vue').then(m => m.default) },
]},
- { path: '/@:user/pages/:page', component: UI, props: route => ({ component: () => import('../common/views/pages/page/page.vue').then(m => m.default), pageName: route.params.page, username: route.params.user }) },
+ { path: '/@:user/pages/:page', component: UI, props: route => ({ component: () => import('../common/views/pages/page.vue').then(m => m.default), pageName: route.params.page, username: route.params.user }) },
{ path: '/@:user/pages/:pageName/view-source', component: UI, props: route => ({ component: () => import('../common/views/pages/page-editor/page-editor.vue').then(m => m.default), initUser: route.params.user, initPageName: route.params.pageName }) },
{ path: '/notes/:note', component: MkNote },
{ path: '/authorize-follow', component: MkFollow },
diff --git a/src/client/app/mobile/views/components/notification.vue b/src/client/app/mobile/views/components/notification.vue
index 9dae95c9b1..448d22cbe6 100644
--- a/src/client/app/mobile/views/components/notification.vue
+++ b/src/client/app/mobile/views/components/notification.vue
@@ -10,7 +10,7 @@
</header>
<router-link class="note-ref" :to="notification.note | notePage" :title="getNoteSummary(notification.note)">
<fa icon="quote-left"/>
- <mfm :text="getNoteSummary(notification.note)" :should-break="false" :plain-text="true" :custom-emojis="notification.note.emojis"/>
+ <mfm :text="getNoteSummary(notification.note)" :plain="true" :nowrap="true" :custom-emojis="notification.note.emojis"/>
<fa icon="quote-right"/>
</router-link>
</div>
@@ -26,7 +26,7 @@
</header>
<router-link class="note-ref" :to="notification.note | notePage" :title="getNoteSummary(notification.note.renote)">
<fa icon="quote-left"/>
- <mfm :text="getNoteSummary(notification.note.renote)" :should-break="false" :plain-text="true" :custom-emojis="notification.note.renote.emojis"/>
+ <mfm :text="getNoteSummary(notification.note.renote)" :plain="true" :nowrap="true" :custom-emojis="notification.note.renote.emojis"/>
<fa icon="quote-right"/>
</router-link>
</div>
@@ -64,7 +64,7 @@
</header>
<router-link class="note-ref" :to="notification.note | notePage" :title="getNoteSummary(notification.note)">
<fa icon="quote-left"/>
- <mfm :text="getNoteSummary(notification.note)" :should-break="false" :plain-text="true" :custom-emojis="notification.note.emojis"/>
+ <mfm :text="getNoteSummary(notification.note)" :plain="true" :nowrap="true" :custom-emojis="notification.note.emojis"/>
<fa icon="quote-right"/>
</router-link>
</div>
diff --git a/src/client/app/mobile/views/pages/settings.vue b/src/client/app/mobile/views/pages/settings.vue
index da01ef6221..c24a56be7b 100644
--- a/src/client/app/mobile/views/pages/settings.vue
+++ b/src/client/app/mobile/views/pages/settings.vue
@@ -3,7 +3,7 @@
<template #header><span style="margin-right:4px;"><fa icon="cog"/></span>{{ $t('@.settings') }}</template>
<main>
<div class="signed-in-as" :class="{ shadow: $store.state.device.useShadow, round: $store.state.device.roundedCorners }">
- <mfm :text="$t('signed-in-as').replace('{}', name)" :should-break="false" :plain-text="true" :custom-emojis="$store.state.i.emojis"/>
+ <mfm :text="$t('signed-in-as').replace('{}', name)" :plain="true" :custom-emojis="$store.state.i.emojis"/>
</div>
<x-settings/>
diff --git a/src/client/app/mobile/views/pages/user/home.vue b/src/client/app/mobile/views/pages/user/home.vue
index 1d7b0a4e6d..316b2a12fe 100644
--- a/src/client/app/mobile/views/pages/user/home.vue
+++ b/src/client/app/mobile/views/pages/user/home.vue
@@ -1,5 +1,6 @@
<template>
<div class="wojmldye">
+ <x-page class="page" v-if="user.pinnedPage" :page="user.pinnedPage" :key="user.pinnedPage.id" :show-title="!user.pinnedPage.hideTitleWhenPinned"/>
<mk-note-detail class="note" v-for="n in user.pinnedNotes" :key="n.id" :note="n" :compact="true"/>
<ui-container :body-togglable="true">
<template #header><fa :icon="['far', 'comments']"/>{{ $t('recent-notes') }}</template>
@@ -33,6 +34,7 @@ export default Vue.extend({
components: {
XNotes,
XPhotos,
+ XPage: () => import('../../../../common/views/components/page/page.vue').then(m => m.default),
XActivity: () => import('../../../../common/views/components/activity.vue').then(m => m.default)
},
props: ['user'],
@@ -53,6 +55,12 @@ export default Vue.extend({
<style lang="stylus" scoped>
.wojmldye
+ > .page
+ margin 0 0 8px 0
+
+ @media (min-width 500px)
+ margin 0 0 16px 0
+
> .note
margin 0 0 8px 0
diff --git a/src/client/app/mobile/views/pages/user/index.vue b/src/client/app/mobile/views/pages/user/index.vue
index f8f4719a68..2e4998178f 100644
--- a/src/client/app/mobile/views/pages/user/index.vue
+++ b/src/client/app/mobile/views/pages/user/index.vue
@@ -28,7 +28,7 @@
<div class="fields" v-if="user.fields">
<dl class="field" v-for="(field, i) in user.fields" :key="i">
<dt class="name">
- <mfm :text="field.name" :should-break="false" :plain-text="true" :custom-emojis="user.emojis"/>
+ <mfm :text="field.name" :plain="true" :custom-emojis="user.emojis"/>
</dt>
<dd class="value">
<mfm :text="field.value" :author="user" :i="$store.state.i" :custom-emojis="user.emojis"/>
diff --git a/src/client/app/store.ts b/src/client/app/store.ts
index 852d2c393d..18137c1ca9 100644
--- a/src/client/app/store.ts
+++ b/src/client/app/store.ts
@@ -38,6 +38,9 @@ const defaultSettings = {
homeProfiles: {},
mobileHomeProfiles: {},
deckProfiles: {},
+ uploadFolder: null,
+ pastedFileName: 'yyyy-MM-dd HH-mm-ss [{{number}}]',
+ pasteDialog: false,
};
const defaultDeviceSettings = {
@@ -60,6 +63,7 @@ const defaultDeviceSettings = {
soundVolume: 0.5,
mediaVolume: 0.5,
lang: null,
+ appTypeForce: 'auto',
debug: false,
lightmode: false,
loadRawImages: false,