1
0
mirror of https://github.com/hotomoe/hotomoe synced 2024-11-28 23:08:17 +09:00

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'], const emit = defineEmits<{
(ev: 'closed'): void;
}>();
data() { const preferedModalType = (deviceKind === 'desktop' && props.src != null) ? 'popup' :
return { deviceKind === 'smartphone' ? 'drawer' :
menuDef: menuDef, 'dialog';
items: [],
instanceName,
};
},
computed: { const modal = $ref<InstanceType<typeof MkModal>>();
menu(): string[] {
return this.$store.state.menu;
},
},
created() { const menu = defaultStore.state.menu;
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 => ({
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', type: def.to ? 'link' : 'button',
text: this.$ts[def.title], text: i18n.ts[def.title],
icon: def.icon, icon: def.icon,
to: def.to, to: def.to,
action: def.action, action: def.action,
indicate: def.indicated, indicate: def.indicated,
})); }));
},
methods: { function close() {
close() { modal.close();
this.$refs.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: 128px;
border-radius: var(--radius);
@media (max-width: 500px) {
width: 100px;
height: 100px; height: 100px;
} border-radius: 10px;
&: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,24 +25,20 @@
<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({
setup(props, context) {
const iconOnly = ref(false); const iconOnly = ref(false);
const menu = computed(() => defaultStore.state.menu); const menu = computed(() => defaultStore.state.menu);
@ -66,28 +62,18 @@ export default defineComponent({
calcViewState(); calcViewState();
}); });
return { function openAccountMenu(ev: MouseEvent) {
host: host, openAccountMenu_({
accounts: [],
connection: null,
menu,
menuDef: menuDef,
otherMenuItemIndicated,
iconOnly,
post: os.post,
search,
openAccountMenu:(ev) => {
openAccountMenu({
withExtraOperation: true, withExtraOperation: true,
}, ev); }, ev);
}, }
more: () => {
os.popup(import('@/components/launch-pad.vue'), {}, { function more(ev: MouseEvent) {
os.popup(import('@/components/launch-pad.vue'), {
src: ev.currentTarget ?? ev.target,
}, {
}, 'closed'); }, 'closed');
}, }
};
},
});
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>

View File

@ -101,7 +101,9 @@ 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');
}, },

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');
}, },