diff options
Diffstat (limited to 'src')
27 files changed, 214 insertions, 94 deletions
@@ -90,6 +90,7 @@ export default { }, sitename () { return this.$store.state.instance.name }, chat () { return this.$store.state.chat.channel.state === 'joined' }, + hideSitename () { return this.$store.state.instance.hideSitename }, suggestionsEnabled () { return this.$store.state.instance.suggestionsEnabled }, showInstanceSpecificPanel () { return this.$store.state.instance.showInstanceSpecificPanel && @@ -97,7 +98,8 @@ export default { this.$store.state.instance.instanceSpecificPanelContent }, showFeaturesPanel () { return this.$store.state.instance.showFeaturesPanel }, - isMobileLayout () { return this.$store.state.interface.mobileLayout } + isMobileLayout () { return this.$store.state.interface.mobileLayout }, + privateMode () { return this.$store.state.instance.private } }, methods: { scrollToTop () { diff --git a/src/App.scss b/src/App.scss index 925913f2..754ca62e 100644 --- a/src/App.scss +++ b/src/App.scss @@ -870,3 +870,16 @@ nav { transform: rotate(359deg); } } + +.new-status-notification { + position:relative; + margin-top: -1px; + font-size: 1.1em; + border-width: 1px 0 0 0; + border-style: solid; + border-color: var(--border, $fallback--border); + padding: 10px; + z-index: 1; + background-color: $fallback--fg; + background-color: var(--panel, $fallback--fg); +} diff --git a/src/App.vue b/src/App.vue index dbe842ec..1b1c2648 100644 --- a/src/App.vue +++ b/src/App.vue @@ -31,6 +31,7 @@ </div> <div class="item"> <router-link + v-if="!hideSitename" class="site-name" :to="{ name: 'root' }" active-class="home" @@ -40,6 +41,7 @@ </div> <div class="item right"> <search-bar + v-if="currentUser || !privateMode" class="nav-icon mobile-hidden" @toggled="onSearchBarToggled" @click.stop.native diff --git a/src/boot/after_store.js b/src/boot/after_store.js index 226b67d8..228a0497 100644 --- a/src/boot/after_store.js +++ b/src/boot/after_store.js @@ -108,6 +108,7 @@ const setSettings = async ({ apiConfig, staticConfig, store }) => { copyInstanceOption('alwaysShowSubjectInput') copyInstanceOption('noAttachmentLinks') copyInstanceOption('showFeaturesPanel') + copyInstanceOption('hideSitename') return store.dispatch('setTheme', config['theme']) } @@ -218,12 +219,21 @@ const getNodeInfo = async ({ store }) => { store.dispatch('setInstanceOption', { name: 'backendVersion', value: software.version }) store.dispatch('setInstanceOption', { name: 'pleromaBackend', value: software.name === 'pleroma' }) + const priv = metadata.private + store.dispatch('setInstanceOption', { name: 'private', value: priv }) + const frontendVersion = window.___pleromafe_commit_hash store.dispatch('setInstanceOption', { name: 'frontendVersion', value: frontendVersion }) store.dispatch('setInstanceOption', { name: 'tagPolicyAvailable', value: metadata.federation.mrf_policies.includes('TagPolicy') }) const federation = metadata.federation store.dispatch('setInstanceOption', { name: 'federationPolicy', value: federation }) + store.dispatch('setInstanceOption', { + name: 'federating', + value: typeof federation.enabled === 'undefined' + ? true + : federation.enabled + }) const accounts = metadata.staffAccounts await resolveStaffAccounts({ store, accounts }) diff --git a/src/components/login_form/login_form.js b/src/components/login_form/login_form.js index 0b574a04..0d8f1da6 100644 --- a/src/components/login_form/login_form.js +++ b/src/components/login_form/login_form.js @@ -58,7 +58,7 @@ const LoginForm = { ).then((result) => { if (result.error) { if (result.error === 'mfa_required') { - this.requireMFA({ app: app, settings: result }) + this.requireMFA({ settings: result }) } else if (result.identifier === 'password_reset_required') { this.$router.push({ name: 'password-reset', params: { passwordResetRequested: true } }) } else { diff --git a/src/components/mfa_form/recovery_form.js b/src/components/mfa_form/recovery_form.js index 7a3cc22d..b25c65dd 100644 --- a/src/components/mfa_form/recovery_form.js +++ b/src/components/mfa_form/recovery_form.js @@ -8,18 +8,23 @@ export default { }), computed: { ...mapGetters({ - authApp: 'authFlow/app', authSettings: 'authFlow/settings' }), - ...mapState({ instance: 'instance' }) + ...mapState({ + instance: 'instance', + oauth: 'oauth' + }) }, methods: { ...mapMutations('authFlow', ['requireTOTP', 'abortMFA']), ...mapActions({ login: 'authFlow/login' }), clearError () { this.error = false }, submit () { + const { clientId, clientSecret } = this.oauth + const data = { - app: this.authApp, + clientId, + clientSecret, instance: this.instance.server, mfaToken: this.authSettings.mfa_token, code: this.code diff --git a/src/components/mfa_form/totp_form.js b/src/components/mfa_form/totp_form.js index 778bf8dc..b774f2d0 100644 --- a/src/components/mfa_form/totp_form.js +++ b/src/components/mfa_form/totp_form.js @@ -7,18 +7,23 @@ export default { }), computed: { ...mapGetters({ - authApp: 'authFlow/app', authSettings: 'authFlow/settings' }), - ...mapState({ instance: 'instance' }) + ...mapState({ + instance: 'instance', + oauth: 'oauth' + }) }, methods: { ...mapMutations('authFlow', ['requireRecovery', 'abortMFA']), ...mapActions({ login: 'authFlow/login' }), clearError () { this.error = false }, submit () { + const { clientId, clientSecret } = this.oauth + const data = { - app: this.authApp, + clientId, + clientSecret, instance: this.instance.server, mfaToken: this.authSettings.mfa_token, code: this.code diff --git a/src/components/mobile_nav/mobile_nav.js b/src/components/mobile_nav/mobile_nav.js index 5a90c31f..c1166a0c 100644 --- a/src/components/mobile_nav/mobile_nav.js +++ b/src/components/mobile_nav/mobile_nav.js @@ -29,6 +29,7 @@ const MobileNav = { unseenNotificationsCount () { return this.unseenNotifications.length }, + hideSitename () { return this.$store.state.instance.hideSitename }, sitename () { return this.$store.state.instance.name } }, methods: { diff --git a/src/components/mobile_nav/mobile_nav.vue b/src/components/mobile_nav/mobile_nav.vue index d1c24e56..51f1d636 100644 --- a/src/components/mobile_nav/mobile_nav.vue +++ b/src/components/mobile_nav/mobile_nav.vue @@ -17,6 +17,7 @@ <i class="button-icon icon-menu" /> </a> <router-link + v-if="!hideSitename" class="site-name" :to="{ name: 'root' }" active-class="home" diff --git a/src/components/nav_panel/nav_panel.js b/src/components/nav_panel/nav_panel.js index 7f783acb..d9268585 100644 --- a/src/components/nav_panel/nav_panel.js +++ b/src/components/nav_panel/nav_panel.js @@ -1,20 +1,18 @@ +import { mapState } from 'vuex' + const NavPanel = { created () { if (this.currentUser && this.currentUser.locked) { this.$store.dispatch('startFetchingFollowRequest') } }, - computed: { - currentUser () { - return this.$store.state.users.currentUser - }, - chat () { - return this.$store.state.chat.channel - }, - followRequestCount () { - return this.$store.state.api.followRequests.length - } - } + computed: mapState({ + currentUser: state => state.users.currentUser, + chat: state => state.chat.channel, + followRequestCount: state => state.api.followRequests.length, + privateMode: state => state.instance.private, + federating: state => state.instance.federating + }) } export default NavPanel diff --git a/src/components/nav_panel/nav_panel.vue b/src/components/nav_panel/nav_panel.vue index 28589bb1..034259d9 100644 --- a/src/components/nav_panel/nav_panel.vue +++ b/src/components/nav_panel/nav_panel.vue @@ -4,22 +4,22 @@ <ul> <li v-if="currentUser"> <router-link :to="{ name: 'friends' }"> - {{ $t("nav.timeline") }} + <i class="button-icon icon-home-2" /> {{ $t("nav.timeline") }} </router-link> </li> <li v-if="currentUser"> <router-link :to="{ name: 'interactions', params: { username: currentUser.screen_name } }"> - {{ $t("nav.interactions") }} + <i class="button-icon icon-bell-alt" /> {{ $t("nav.interactions") }} </router-link> </li> <li v-if="currentUser"> <router-link :to="{ name: 'dms', params: { username: currentUser.screen_name } }"> - {{ $t("nav.dms") }} + <i class="button-icon icon-mail-alt" /> {{ $t("nav.dms") }} </router-link> </li> <li v-if="currentUser && currentUser.locked"> <router-link :to="{ name: 'friend-requests' }"> - {{ $t("nav.friend_requests") }} + <i class="button-icon icon-user-plus" /> {{ $t("nav.friend_requests") }} <span v-if="followRequestCount > 0" class="badge follow-request-count" @@ -28,19 +28,19 @@ </span> </router-link> </li> - <li> + <li v-if="currentUser || !privateMode"> <router-link :to="{ name: 'public-timeline' }"> - {{ $t("nav.public_tl") }} + <i class="button-icon icon-users" /> {{ $t("nav.public_tl") }} </router-link> </li> - <li> + <li v-if="federating && !privateMode"> <router-link :to="{ name: 'public-external-timeline' }"> - {{ $t("nav.twkn") }} + <i class="button-icon icon-globe" /> {{ $t("nav.twkn") }} </router-link> </li> <li> <router-link :to="{ name: 'about' }"> - {{ $t("nav.about") }} + <i class="button-icon icon-info-circled" /> {{ $t("nav.about") }} </router-link> </li> </ul> @@ -113,4 +113,8 @@ } } } + +.nav-panel .button-icon:before { + width: 1.1em; +} </style> diff --git a/src/components/post_status_form/post_status_form.js b/src/components/post_status_form/post_status_form.js index af6299e4..74067fef 100644 --- a/src/components/post_status_form/post_status_form.js +++ b/src/components/post_status_form/post_status_form.js @@ -169,9 +169,7 @@ const PostStatusForm = { if (this.submitDisabled) { return } if (this.newStatus.status === '') { - if (this.newStatus.files.length > 0) { - this.newStatus.status = '\u200b' // hack - } else { + if (this.newStatus.files.length === 0) { this.error = 'Cannot post an empty status with no files' return } diff --git a/src/components/registration/registration.vue b/src/components/registration/registration.vue index 5bb06a4f..222b67a8 100644 --- a/src/components/registration/registration.vue +++ b/src/components/registration/registration.vue @@ -172,7 +172,7 @@ for="captcha-label" >{{ $t('captcha') }}</label> - <template v-if="captcha.type == 'kocaptcha'"> + <template v-if="['kocaptcha', 'native'].includes(captcha.type)"> <img :src="captcha.url" @click="setCaptcha" diff --git a/src/components/side_drawer/side_drawer.js b/src/components/side_drawer/side_drawer.js index 0188cf3e..2534eb8f 100644 --- a/src/components/side_drawer/side_drawer.js +++ b/src/components/side_drawer/side_drawer.js @@ -33,11 +33,20 @@ const SideDrawer = { logo () { return this.$store.state.instance.logo }, + hideSitename () { + return this.$store.state.instance.hideSitename + }, sitename () { return this.$store.state.instance.name }, followRequestCount () { return this.$store.state.api.followRequests.length + }, + privateMode () { + return this.$store.state.instance.private + }, + federating () { + return this.$store.state.instance.federating } }, methods: { diff --git a/src/components/side_drawer/side_drawer.vue b/src/components/side_drawer/side_drawer.vue index 214b8e0c..3fba9058 100644 --- a/src/components/side_drawer/side_drawer.vue +++ b/src/components/side_drawer/side_drawer.vue @@ -27,7 +27,7 @@ class="side-drawer-logo-wrapper" > <img :src="logo"> - <span>{{ sitename }}</span> + <span v-if="!hideSitename">{{ sitename }}</span> </div> </div> <ul> @@ -36,7 +36,7 @@ @click="toggleDrawer" > <router-link :to="{ name: 'login' }"> - {{ $t("login.login") }} + <i class="button-icon icon-login" /> {{ $t("login.login") }} </router-link> </li> <li @@ -44,7 +44,7 @@ @click="toggleDrawer" > <router-link :to="{ name: 'dms', params: { username: currentUser.screen_name } }"> - {{ $t("nav.dms") }} + <i class="button-icon icon-mail-alt" /> {{ $t("nav.dms") }} </router-link> </li> <li @@ -52,7 +52,7 @@ @click="toggleDrawer" > <router-link :to="{ name: 'interactions', params: { username: currentUser.screen_name } }"> - {{ $t("nav.interactions") }} + <i class="button-icon icon-bell-alt" /> {{ $t("nav.interactions") }} </router-link> </li> </ul> @@ -62,7 +62,7 @@ @click="toggleDrawer" > <router-link :to="{ name: 'friends' }"> - {{ $t("nav.timeline") }} + <i class="button-icon icon-home-2" /> {{ $t("nav.timeline") }} </router-link> </li> <li @@ -70,7 +70,7 @@ @click="toggleDrawer" > <router-link to="/friend-requests"> - {{ $t("nav.friend_requests") }} + <i class="button-icon icon-user-plus" /> {{ $t("nav.friend_requests") }} <span v-if="followRequestCount > 0" class="badge follow-request-count" @@ -79,14 +79,20 @@ </span> </router-link> </li> - <li @click="toggleDrawer"> + <li + v-if="currentUser || !privateMode" + @click="toggleDrawer" + > <router-link to="/main/public"> - {{ $t("nav.public_tl") }} + <i class="button-icon icon-users" /> {{ $t("nav.public_tl") }} </router-link> </li> - <li @click="toggleDrawer"> + <li + v-if="federating && !privateMode" + @click="toggleDrawer" + > <router-link to="/main/all"> - {{ $t("nav.twkn") }} + <i class="button-icon icon-globe" /> {{ $t("nav.twkn") }} </router-link> </li> <li @@ -94,14 +100,17 @@ @click="toggleDrawer" > <router-link :to="{ name: 'chat' }"> - {{ $t("nav.chat") }} + <i class="button-icon icon-chat" /> {{ $t("nav.chat") }} </router-link> </li> </ul> <ul> - <li @click="toggleDrawer"> + <li + v-if="currentUser || !privateMode" + @click="toggleDrawer" + > <router-link :to="{ name: 'search' }"> - {{ $t("nav.search") }} + <i class="button-icon icon-search" /> {{ $t("nav.search") }} </router-link> </li> <li @@ -109,17 +118,17 @@ @click="toggleDrawer" > <router-link :to="{ name: 'who-to-follow' }"> - {{ $t("nav.who_to_follow") }} + <i class="button-icon icon-user-plus" /> {{ $t("nav.who_to_follow") }} </router-link> </li> <li @click="toggleDrawer"> <router-link :to="{ name: 'settings' }"> - {{ $t("settings.settings") }} + <i class="button-icon icon-cog" /> {{ $t("settings.settings") }} </router-link> </li> <li @click="toggleDrawer"> <router-link :to="{ name: 'about'}"> - {{ $t("nav.about") }} + <i class="button-icon icon-info-circled" /> {{ $t("nav.about") }} </router-link> </li> <li @@ -130,7 +139,7 @@ href="/pleroma/admin/#/login-pleroma" target="_blank" > - {{ $t("nav.administration") }} + <i class="button-icon icon-gauge" /> {{ $t("nav.administration") }} </a> </li> <li @@ -141,7 +150,7 @@ href="#" @click="doLogout" > - {{ $t("login.logout") }} + <i class="button-icon icon-logout" /> {{ $t("login.logout") }} </a> </li> </ul> @@ -215,6 +224,10 @@ box-shadow: var(--panelShadow); background-color: $fallback--bg; background-color: var(--bg, $fallback--bg); + + .button-icon:before { + width: 1.1em; + } } .side-drawer-logo-wrapper { diff --git a/src/components/timeline/timeline.js b/src/components/timeline/timeline.js index 27a9a55e..9a53acd6 100644 --- a/src/components/timeline/timeline.js +++ b/src/components/timeline/timeline.js @@ -36,7 +36,12 @@ const Timeline = { } }, computed: { - timelineError () { return this.$store.state.statuses.error }, + timelineError () { + return this.$store.state.statuses.error + }, + errorData () { + return this.$store.state.statuses.errorData + }, newStatusCount () { return this.timeline.newStatusCount }, diff --git a/src/components/timeline/timeline.vue b/src/components/timeline/timeline.vue index 93f6f570..9777bd0c 100644 --- a/src/components/timeline/timeline.vue +++ b/src/components/timeline/timeline.vue @@ -11,15 +11,22 @@ > {{ $t('timeline.error_fetching') }} </div> + <div + v-else-if="errorData" + class="loadmore-error alert error" + @click.prevent + > + {{ errorData.statusText }} + </div> <button - v-if="timeline.newStatusCount > 0 && !timelineError" + v-if="timeline.newStatusCount > 0 && !timelineError && !errorData" class="loadmore-button" @click.prevent="showNewStatuses" > {{ $t('timeline.show_new') }}{{ newStatusCountStr }} </button> <div - v-if="!timeline.newStatusCount > 0 && !timelineError" + v-if="!timeline.newStatusCount > 0 && !timelineError && !errorData" class="loadmore-text faint" @click.prevent > @@ -67,12 +74,18 @@ {{ $t('timeline.no_more_statuses') }} </div> <a - v-else-if="!timeline.loading" + v-else-if="!timeline.loading && !errorData" href="#" @click.prevent="fetchOlderStatuses()" > <div class="new-status-notification text-center panel-footer">{{ $t('timeline.load_older') }}</div> </a> + <a + v-else-if="errorData" + href="#" + > + <div class="new-status-notification text-center panel-footer">{{ errorData.error }}</div> + </a> <div v-else class="new-status-notification text-center panel-footer" @@ -93,17 +106,4 @@ opacity: 1; } } - -.new-status-notification { - position:relative; - margin-top: -1px; - font-size: 1.1em; - border-width: 1px 0 0 0; - border-style: solid; - border-color: var(--border, $fallback--border); - padding: 10px; - z-index: 1; - background-color: $fallback--fg; - background-color: var(--panel, $fallback--fg); -} </style> diff --git a/src/hocs/with_load_more/with_load_more.js b/src/hocs/with_load_more/with_load_more.js index 1e1b2a74..6142f513 100644 --- a/src/hocs/with_load_more/with_load_more.js +++ b/src/hocs/with_load_more/with_load_more.js @@ -65,7 +65,7 @@ const withLoadMore = ({ } } }, - render (createElement) { + render (h) { const props = { props: { ...this.$props, @@ -74,7 +74,7 @@ const withLoadMore = ({ on: this.$listeners, scopedSlots: this.$scopedSlots } - const children = Object.entries(this.$slots).map(([key, value]) => createElement('template', { slot: key }, value)) + const children = Object.entries(this.$slots).map(([key, value]) => h('template', { slot: key }, value)) return ( <div class="with-load-more"> <WrappedComponent {...props}> diff --git a/src/hocs/with_subscription/with_subscription.js b/src/hocs/with_subscription/with_subscription.js index 91fc4cca..1775adcb 100644 --- a/src/hocs/with_subscription/with_subscription.js +++ b/src/hocs/with_subscription/with_subscription.js @@ -49,7 +49,7 @@ const withSubscription = ({ } } }, - render (createElement) { + render (h) { if (!this.error && !this.loading) { const props = { props: { @@ -59,7 +59,7 @@ const withSubscription = ({ on: this.$listeners, scopedSlots: this.$scopedSlots } - const children = Object.entries(this.$slots).map(([key, value]) => createElement('template', { slot: key }, value)) + const children = Object.entries(this.$slots).map(([key, value]) => h('template', { slot: key }, value)) return ( <div class="with-subscription"> <WrappedComponent {...props}> diff --git a/src/i18n/ja_easy.json b/src/i18n/ja_easy.json index 592a7257..be447f1c 100644 --- a/src/i18n/ja_easy.json +++ b/src/i18n/ja_easy.json @@ -1,4 +1,23 @@ { + "about": { + "staff": "スタッフ", + "federation": "フェデレーション", + "mrf_policies": "ゆうこうなMRFポリシー", + "mrf_policies_desc": "MRFポリシーは、このインスタンスのフェデレーションのふるまいを、いじります。これらのMRFポリシーがゆうこうになっています:", + "mrf_policy_simple": "インスタンスのポリシー", + "mrf_policy_simple_accept": "うけいれ", + "mrf_policy_simple_accept_desc": "このインスンスは、これらのインスタンスからのメッセージのみをうけいれます:", + "mrf_policy_simple_reject": "おことわり", + "mrf_policy_simple_reject_desc": "このインスタンスは、これらのインスタンスからのメッセージをうけいれません:", + "mrf_policy_simple_quarantine": "けんえき", + "mrf_policy_simple_quarantine_desc": "このインスタンスは、これらのインスタンスに、パブリックなとうこうのみを、おくります:", + "mrf_policy_simple_ftl_removal": "「つながっているすべてのネットワーク」タイムラインからのぞく", + "mrf_policy_simple_ftl_removal_desc": "このインスタンスは、つながっているすべてのネットワーク」タイムラインから、これらのインスタンスを、とりのぞきます:", + "mrf_policy_simple_media_removal": "メディアをのぞく", + "mrf_policy_simple_media_removal_desc": "このインスタンスは、これらのインスタンスからおくられてきたメディアを、とりのぞきます:", + "mrf_policy_simple_media_nsfw": "メディアをすべてセンシティブにする", + "mrf_policy_simple_media_nsfw_desc": "このインスタンスは、これらのインスタンスからおくられてきたメディアを、すべて、センシティブにマークします:" + }, "chat": { "title": "チャット" }, @@ -68,6 +87,7 @@ }, "nav": { "about": "これはなに?", + "administration": "アドミニストレーション", "back": "もどる", "chat": "ローカルチャット", "friend_requests": "フォローリクエスト", @@ -113,7 +133,9 @@ "search_emoji": "えもじをさがす", "add_emoji": "えもじをうちこむ", "custom": "カスタムえもじ", - "unicode": "ユニコードえもじ" + "unicode": "ユニコードえもじ", + "load_all_hint": "はじめの {saneAmount} このえもじだけがロードされています。すべてのえもじをロードすると、パフォーマンスがわるくなるかもしれません。", + "load_all": "すべてのえもじをロード ({emojiAmount} こあります)" }, "stickers": { "add_sticker": "ステッカーをふやす" @@ -173,6 +195,11 @@ "password_confirmation_match": "パスワードがちがいます" } }, + "remote_user_resolver": { + "remote_user_resolver": "リモートユーザーリゾルバー", + "searching_for": "さがしています:", + "error": "みつかりませんでした。" + }, "selectable_list": { "select_all": "すべてえらぶ" }, @@ -220,6 +247,9 @@ "cGreen": "リピート", "cOrange": "おきにいり", "cRed": "キャンセル", + "change_email": "メールアドレスをかえる", + "change_email_error": "メールアドレスをかえようとしましたが、なにかがおかしいです。", + "changed_email": "メールアドレスをかえることができました!", "change_password": "パスワードをかえる", "change_password_error": "パスワードをかえることが、できなかったかもしれません。", "changed_password": "パスワードが、かわりました!", @@ -279,6 +309,7 @@ "use_contain_fit": "がぞうのサムネイルを、きりぬかない", "name": "なまえ", "name_bio": "なまえとプロフィール", + "new_email": "あたらしいメールアドレス", "new_password": "あたらしいパスワード", "notification_visibility": "ひょうじするつうち", "notification_visibility_follows": "フォロー", @@ -344,6 +375,8 @@ "false": "いいえ", "true": "はい" }, + "fun": "おたのしみ", + "greentext": "ミームやじるし", "notifications": "つうち", "notification_setting": "つうちをうけとる:", "notification_setting_follows": "あなたがフォローしているひとから", @@ -391,6 +424,7 @@ "_tab_label": "くわしく", "alert": "アラートのバックグラウンド", "alert_error": "エラー", + "alert_warning": "けいこく", "badge": "バッジのバックグラウンド", "badge_notification": "つうち", "panel_header": "パネルヘッダー", @@ -542,6 +576,7 @@ "followers": "フォロワー", "following": "フォローしています!", "follows_you": "フォローされました!", + "hidden": "かくされています", "its_you": "これはあなたです!", "media": "メディア", "mention": "メンション", @@ -559,6 +594,8 @@ "unmute": "ミュートをやめる", "unmute_progress": "ミュートをとりけしています...", "mute_progress": "ミュートしています...", + "hide_repeats": "リピートをかくす", + "show_repeats": "リピートをみる", "admin_menu": { "moderation": "モデレーション", "grant_admin": "アドミンにする", @@ -634,6 +671,8 @@ "return_home": "ホームページにもどる", "not_found": "そのメールアドレスまたはユーザーめいを、みつけることができませんでした。", "too_many_requests": "パスワードリセットを、ためすことが、おおすぎます。しばらくしてから、ためしてください。", - "password_reset_disabled": "このインスタンスでは、パスワードリセットは、できません。インスタンスのアドミニストレーターに、おといあわせください。" + "password_reset_disabled": "このインスタンスでは、パスワードリセットは、できません。インスタンスのアドミニストレーターに、おといあわせください。", + "password_reset_required": "ログインするには、パスワードをリセットしてください。", + "password_reset_required_but_mailer_is_disabled": "あなたはパスワードのリセットがひつようです。しかし、まずいことに、このインスタンスでは、パスワードのリセットができなくなっています。このインスタンスのアドミニストレーターに、おといあわせください。" } } diff --git a/src/modules/auth_flow.js b/src/modules/auth_flow.js index d0a90feb..956d40e8 100644 --- a/src/modules/auth_flow.js +++ b/src/modules/auth_flow.js @@ -7,7 +7,6 @@ const RECOVERY_STRATEGY = 'recovery' // initial state const state = { - app: null, settings: {}, strategy: PASSWORD_STRATEGY, initStrategy: PASSWORD_STRATEGY // default strategy from config @@ -16,14 +15,10 @@ const state = { const resetState = (state) => { state.strategy = state.initStrategy state.settings = {} - state.app = null } // getters const getters = { - app: (state, getters) => { - return state.app - }, settings: (state, getters) => { return state.settings }, @@ -55,9 +50,8 @@ const mutations = { requireToken (state) { state.strategy = TOKEN_STRATEGY }, - requireMFA (state, { app, settings }) { + requireMFA (state, { settings }) { state.settings = settings - state.app = app state.strategy = TOTP_STRATEGY // default strategy of MFA }, requireRecovery (state) { diff --git a/src/modules/instance.js b/src/modules/instance.js index 96f14ed5..625323b9 100644 --- a/src/modules/instance.js +++ b/src/modules/instance.js @@ -27,6 +27,7 @@ const defaultState = { scopeCopy: true, subjectLineBehavior: 'email', postContentType: 'text/plain', + hideSitename: false, nsfwCensorImage: undefined, vapidPublicKey: undefined, noAttachmentLinks: false, diff --git a/src/modules/statuses.js b/src/modules/statuses.js index f11ffdcd..e3a1f293 100644 --- a/src/modules/statuses.js +++ b/src/modules/statuses.js @@ -38,6 +38,7 @@ export const defaultState = () => ({ notifications: emptyNotifications(), favorites: new Set(), error: false, + errorData: null, timelines: { mentions: emptyTl(), public: emptyTl(), @@ -479,6 +480,9 @@ export const mutations = { setError (state, { value }) { state.error = value }, + setErrorData (state, { value }) { + state.errorData = value + }, setNotificationsLoading (state, { value }) { state.notifications.loading = value }, @@ -528,6 +532,9 @@ const statuses = { setError ({ rootState, commit }, { value }) { commit('setError', { value }) }, + setErrorData ({ rootState, commit }, { value }) { + commit('setErrorData', { value }) + }, setNotificationsLoading ({ rootState, commit }, { value }) { commit('setNotificationsLoading', { value }) }, diff --git a/src/services/api/api.service.js b/src/services/api/api.service.js index 8f5eb416..7eb0547e 100644 --- a/src/services/api/api.service.js +++ b/src/services/api/api.service.js @@ -22,7 +22,7 @@ const MFA_BACKUP_CODES_URL = '/api/pleroma/accounts/mfa/backup_codes' const MFA_SETUP_OTP_URL = '/api/pleroma/accounts/mfa/setup/totp' const MFA_CONFIRM_OTP_URL = '/api/pleroma/accounts/mfa/confirm/totp' -const MFA_DISABLE_OTP_URL = '/api/pleroma/account/mfa/totp' +const MFA_DISABLE_OTP_URL = '/api/pleroma/accounts/mfa/totp' const MASTODON_LOGIN_URL = '/api/v1/accounts/verify_credentials' const MASTODON_REGISTRATION_URL = '/api/v1/accounts' @@ -529,16 +529,24 @@ const fetchTimeline = ({ const queryString = map(params, (param) => `${param[0]}=${param[1]}`).join('&') url += `?${queryString}` - + let status = '' + let statusText = '' return fetch(url, { headers: authHeaders(credentials) }) .then((data) => { - if (data.ok) { + status = data.status + statusText = data.statusText + return data + }) + .then((data) => data.json()) + .then((data) => { + if (!data.error) { + return data.map(isNotifications ? parseNotification : parseStatus) + } else { + data.status = status + data.statusText = statusText return data } - throw new Error('Error fetching timeline', data) }) - .then((data) => data.json()) - .then((data) => data.map(isNotifications ? parseNotification : parseStatus)) } const fetchPinnedStatuses = ({ id, credentials }) => { diff --git a/src/services/new_api/mfa.js b/src/services/new_api/mfa.js index cbba06d5..c944667c 100644 --- a/src/services/new_api/mfa.js +++ b/src/services/new_api/mfa.js @@ -1,9 +1,9 @@ -const verifyOTPCode = ({ app, instance, mfaToken, code }) => { +const verifyOTPCode = ({ clientId, clientSecret, instance, mfaToken, code }) => { const url = `${instance}/oauth/mfa/challenge` const form = new window.FormData() - form.append('client_id', app.client_id) - form.append('client_secret', app.client_secret) + form.append('client_id', clientId) + form.append('client_secret', clientSecret) form.append('mfa_token', mfaToken) form.append('code', code) form.append('challenge_type', 'totp') @@ -14,12 +14,12 @@ const verifyOTPCode = ({ app, instance, mfaToken, code }) => { }).then((data) => data.json()) } -const verifyRecoveryCode = ({ app, instance, mfaToken, code }) => { +const verifyRecoveryCode = ({ clientId, clientSecret, instance, mfaToken, code }) => { const url = `${instance}/oauth/mfa/challenge` const form = new window.FormData() - form.append('client_id', app.client_id) - form.append('client_secret', app.client_secret) + form.append('client_id', clientId) + form.append('client_secret', clientSecret) form.append('mfa_token', mfaToken) form.append('code', code) form.append('challenge_type', 'recovery') diff --git a/src/services/new_api/oauth.js b/src/services/new_api/oauth.js index d0d18c03..3c8e64bd 100644 --- a/src/services/new_api/oauth.js +++ b/src/services/new_api/oauth.js @@ -12,7 +12,7 @@ export const getOrCreateApp = ({ clientId, clientSecret, instance, commit }) => form.append('client_name', `PleromaFE_${window.___pleromafe_commit_hash}_${(new Date()).toISOString()}`) form.append('redirect_uris', REDIRECT_URI) - form.append('scopes', 'read write follow') + form.append('scopes', 'read write follow push admin') return window.fetch(url, { method: 'POST', @@ -28,7 +28,7 @@ const login = ({ instance, clientId }) => { response_type: 'code', client_id: clientId, redirect_uri: REDIRECT_URI, - scope: 'read write follow' + scope: 'read write follow push admin' } const dataString = reduce(data, (acc, v, k) => { diff --git a/src/services/timeline_fetcher/timeline_fetcher.service.js b/src/services/timeline_fetcher/timeline_fetcher.service.js index 9eb30c2d..c6b28ad5 100644 --- a/src/services/timeline_fetcher/timeline_fetcher.service.js +++ b/src/services/timeline_fetcher/timeline_fetcher.service.js @@ -6,6 +6,7 @@ const update = ({ store, statuses, timeline, showImmediately, userId }) => { const ccTimeline = camelCase(timeline) store.dispatch('setError', { value: false }) + store.dispatch('setErrorData', { value: null }) store.dispatch('addNewStatuses', { timeline: ccTimeline, @@ -45,6 +46,10 @@ const fetchAndUpdate = ({ return apiService.fetchTimeline(args) .then((statuses) => { + if (statuses.error) { + store.dispatch('setErrorData', { value: statuses }) + return + } if (!older && statuses.length >= 20 && !timelineData.loading && numStatusesBeforeFetch > 0) { store.dispatch('queueFlush', { timeline: timeline, id: timelineData.maxId }) } |
