enhance(client): improve launch pad usability

This commit is contained in:
syuilo 2022-02-23 23:40:31 +09:00
parent 28a24d30d2
commit c0fd7697b9
5 changed files with 103 additions and 116 deletions

View file

@ -1,6 +1,6 @@
<template> <template>
<MkModal ref="modal" :prefer-type="'dialog'" @click="$refs.modal.close()" @closed="$emit('closed')"> <MkModal ref="modal" v-slot="{ type, maxHeight }" :prefer-type="preferedModalType" :transparent-bg="type === 'popup'" :src="src" @click="modal.close()" @closed="emit('closed')">
<div class="szkkfdyq _popup"> <div class="szkkfdyq _popup _shadow" :class="{ asDrawer: type === 'drawer' }" :style="{ maxHeight: maxHeight ? maxHeight + 'px' : '' }">
<div class="main"> <div class="main">
<template v-for="item in items"> <template v-for="item in items">
<button v-if="item.action" v-click-anime class="_button" @click="$event => { item.action($event); close(); }"> <button v-if="item.action" v-click-anime class="_button" @click="$event => { item.action($event); close(); }">
@ -33,97 +33,94 @@
</MkModal> </MkModal>
</template> </template>
<script lang="ts"> <script lang="ts" setup>
import { defineComponent } from 'vue'; import { } from 'vue';
import MkModal from '@/components/ui/modal.vue'; import MkModal from '@/components/ui/modal.vue';
import { menuDef } from '@/menu'; import { menuDef } from '@/menu';
import { instanceName } from '@/config'; import { instanceName } from '@/config';
import { defaultStore } from '@/store';
import { i18n } from '@/i18n';
import { deviceKind } from '@/scripts/device-kind';
export default defineComponent({ const props = withDefaults(defineProps<{
components: { src?: HTMLElement;
MkModal, }>(), {
},
emits: ['closed'],
data() {
return {
menuDef: menuDef,
items: [],
instanceName,
};
},
computed: {
menu(): string[] {
return this.$store.state.menu;
},
},
created() {
this.items = Object.keys(this.menuDef).filter(k => !this.menu.includes(k)).map(k => this.menuDef[k]).filter(def => def.show == null ? true : def.show).map(def => ({
type: def.to ? 'link' : 'button',
text: this.$ts[def.title],
icon: def.icon,
to: def.to,
action: def.action,
indicate: def.indicated,
}));
},
methods: {
close() {
this.$refs.modal.close();
}
}
}); });
const emit = defineEmits<{
(ev: 'closed'): void;
}>();
const preferedModalType = (deviceKind === 'desktop' && props.src != null) ? 'popup' :
deviceKind === 'smartphone' ? 'drawer' :
'dialog';
const modal = $ref<InstanceType<typeof MkModal>>();
const menu = defaultStore.state.menu;
const items = Object.keys(menuDef).filter(k => !menu.includes(k)).map(k => menuDef[k]).filter(def => def.show == null ? true : def.show).map(def => ({
type: def.to ? 'link' : 'button',
text: i18n.ts[def.title],
icon: def.icon,
to: def.to,
action: def.action,
indicate: def.indicated,
}));
function close() {
modal.close();
}
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.szkkfdyq { .szkkfdyq {
width: 100%;
max-height: 100%; max-height: 100%;
max-width: 800px; width: min(460px, 100vw);
padding: 32px; padding: 24px;
box-sizing: border-box; box-sizing: border-box;
overflow: auto; overflow: auto;
text-align: center; overscroll-behavior: contain;
text-align: left;
border-radius: 16px; border-radius: 16px;
@media (max-width: 500px) { &.asDrawer {
padding: 16px; width: 100%;
padding: 16px 16px calc(env(safe-area-inset-bottom, 0px) + 16px) 16px;
border-radius: 24px;
border-bottom-right-radius: 0;
border-bottom-left-radius: 0;
text-align: center;
} }
> .main, > .sub { > .main, > .sub {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(100px, 1fr));
> * { > * {
position: relative; position: relative;
display: inline-flex; display: flex;
flex-direction: column; flex-direction: column;
align-items: center; align-items: center;
justify-content: center; justify-content: center;
vertical-align: bottom; vertical-align: bottom;
width: 128px; height: 100px;
height: 128px; border-radius: 10px;
border-radius: var(--radius);
@media (max-width: 500px) {
width: 100px;
height: 100px;
}
&:hover { &:hover {
background: rgba(0, 0, 0, 0.05); color: var(--accent);
background: var(--accentedBg);
text-decoration: none; text-decoration: none;
} }
> .icon { > .icon {
font-size: 26px; font-size: 24px;
height: 32px; height: 24px;
} }
> .text { > .text {
margin-top: 8px; margin-top: 12px;
font-size: 0.9em; font-size: 0.8em;
line-height: 1.5em; line-height: 1.5em;
} }

View file

@ -88,7 +88,7 @@ const onBgClick = () => {
}; };
if (type.value === 'drawer') { if (type.value === 'drawer') {
maxHeight.value = window.innerHeight / 2; maxHeight.value = window.innerHeight / 1.5;
} }
const keymap = { const keymap = {
@ -100,6 +100,7 @@ const MARGIN = 16;
const align = () => { const align = () => {
if (props.src == null) return; if (props.src == null) return;
if (type.value === 'drawer') return; if (type.value === 'drawer') return;
if (type.value === 'dialog') return;
const popover = content.value!; const popover = content.value!;
if (popover == null) return; if (popover == null) return;

View file

@ -25,69 +25,55 @@
<MkA v-click-anime class="item" active-class="active" to="/settings"> <MkA v-click-anime class="item" active-class="active" to="/settings">
<i class="fas fa-cog fa-fw"></i><span class="text">{{ $ts.settings }}</span> <i class="fas fa-cog fa-fw"></i><span class="text">{{ $ts.settings }}</span>
</MkA> </MkA>
<button class="item _button post" data-cy-open-post-form @click="post"> <button class="item _button post" data-cy-open-post-form @click="os.post">
<i class="fas fa-pencil-alt fa-fw"></i><span class="text">{{ $ts.note }}</span> <i class="fas fa-pencil-alt fa-fw"></i><span class="text">{{ $ts.note }}</span>
</button> </button>
</div> </div>
</div> </div>
</template> </template>
<script lang="ts"> <script lang="ts" setup>
import { computed, defineComponent, ref, watch } from 'vue'; import { computed, ref, watch } from 'vue';
import { host } from '@/config';
import { search } from '@/scripts/search';
import * as os from '@/os'; import * as os from '@/os';
import { menuDef } from '@/menu'; import { menuDef } from '@/menu';
import { openAccountMenu } from '@/account'; import { $i, openAccountMenu as openAccountMenu_ } from '@/account';
import { defaultStore } from '@/store'; import { defaultStore } from '@/store';
export default defineComponent({ const iconOnly = ref(false);
setup(props, context) {
const iconOnly = ref(false);
const menu = computed(() => defaultStore.state.menu); const menu = computed(() => defaultStore.state.menu);
const otherMenuItemIndicated = computed(() => { const otherMenuItemIndicated = computed(() => {
for (const def in menuDef) { for (const def in menuDef) {
if (menu.value.includes(def)) continue; if (menu.value.includes(def)) continue;
if (menuDef[def].indicated) return true; if (menuDef[def].indicated) return true;
} }
return false; return false;
});
const calcViewState = () => {
iconOnly.value = (window.innerWidth <= 1279) || (defaultStore.state.menuDisplay === 'sideIcon');
};
calcViewState();
window.addEventListener('resize', calcViewState);
watch(defaultStore.reactiveState.menuDisplay, () => {
calcViewState();
});
return {
host: host,
accounts: [],
connection: null,
menu,
menuDef: menuDef,
otherMenuItemIndicated,
iconOnly,
post: os.post,
search,
openAccountMenu:(ev) => {
openAccountMenu({
withExtraOperation: true,
}, ev);
},
more: () => {
os.popup(import('@/components/launch-pad.vue'), {}, {
}, 'closed');
},
};
},
}); });
const calcViewState = () => {
iconOnly.value = (window.innerWidth <= 1279) || (defaultStore.state.menuDisplay === 'sideIcon');
};
calcViewState();
window.addEventListener('resize', calcViewState);
watch(defaultStore.reactiveState.menuDisplay, () => {
calcViewState();
});
function openAccountMenu(ev: MouseEvent) {
openAccountMenu_({
withExtraOperation: true,
}, ev);
}
function more(ev: MouseEvent) {
os.popup(import('@/components/launch-pad.vue'), {
src: ev.currentTarget ?? ev.target,
}, {
}, 'closed');
}
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>

View file

@ -101,11 +101,13 @@ export default defineComponent({
}, },
more(ev) { more(ev) {
os.popup(import('@/components/launch-pad.vue'), {}, { os.popup(import('@/components/launch-pad.vue'), {
src: ev.currentTarget ?? ev.target,
}, {
}, 'closed'); }, 'closed');
}, },
openAccountMenu:(ev) => { openAccountMenu: (ev) => {
openAccountMenu({ openAccountMenu({
withExtraOperation: true, withExtraOperation: true,
}, ev); }, ev);

View file

@ -122,6 +122,7 @@ export default defineComponent({
more(ev) { more(ev) {
os.popup(import('@/components/launch-pad.vue'), {}, { os.popup(import('@/components/launch-pad.vue'), {}, {
src: ev.currentTarget ?? ev.target,
}, 'closed'); }, 'closed');
}, },