Skip to content

Commit

Permalink
Add: [Client][Watch/LShapedScreenCropSettings] L字画面のクロップ設定のモーダルを実装
Browse files Browse the repository at this point in the history
設定としては一通り実装したが、まだ機能はしない
  • Loading branch information
tsukumijima committed Aug 24, 2024
1 parent 0b1328b commit 93c5da9
Show file tree
Hide file tree
Showing 7 changed files with 171 additions and 0 deletions.
111 changes: 111 additions & 0 deletions client/src/components/Watch/LShapedScreenCropSettings.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
<template>
<v-dialog max-width="700" transition="slide-y-transition" v-model="playerStore.lshaped_screen_crop_settings_modal">
<v-card>
<v-card-title class="px-5 pt-3 pb-3 d-flex align-center font-weight-bold">
<Icon icon="fluent:screenshot-20-filled" height="28px" />
<span class="ml-4">L字画面のクロップ</span>
<v-spacer></v-spacer>
<v-switch class="mr-4" color="primary" hide-details v-model="settingsStore.settings.lshaped_screen_crop_enabled"></v-switch>
<div v-ripple class="d-flex align-center rounded-circle cursor-pointer px-2 py-2"
@click="playerStore.lshaped_screen_crop_settings_modal = false">
<Icon icon="fluent:dismiss-12-filled" width="23px" height="23px" />
</div>
</v-card-title>
<div class="px-5 pb-6">
<v-slider color="primary" v-model="settingsStore.settings.lshaped_screen_crop_zoom_level" :min="100" :max="200" :step="1"
show-ticks="always" hide-details class="ml-0 mr-0 mb-4">
<template v-slot:prepend>
<div class="d-flex align-center" style="width: 85px;">
<Icon icon="mdi:magnify" width="20px" />
<span class="ml-2">拡大率</span>
</div>
</template>
<template v-slot:append>
<div class="text-right" style="width: 42px;">{{ settingsStore.settings.lshaped_screen_crop_zoom_level }}%</div>
</template>
</v-slider>
<v-slider color="primary" v-model="settingsStore.settings.lshaped_screen_crop_x_position" :min="0" :max="100" :step="1"
show-ticks="always" hide-details class="ml-0 mr-0 mb-4">
<template v-slot:prepend>
<div class="d-flex align-center" style="width: 85px;">
<Icon icon="mdi:arrow-left-right" width="20px" />
<span class="ml-2">X座標</span>
</div>
</template>
<template v-slot:append>
<div class="text-right" style="width: 42px;">{{ settingsStore.settings.lshaped_screen_crop_x_position }}%</div>
</template>
</v-slider>
<v-slider color="primary" v-model="settingsStore.settings.lshaped_screen_crop_y_position" :min="0" :max="100" :step="1"
show-ticks="always" hide-details class="ml-0 mr-0 mb-4">
<template v-slot:prepend>
<div class="d-flex align-center" style="width: 85px;">
<Icon icon="mdi:arrow-up-down" width="20px" />
<span class="ml-2">Y座標</span>
</div>
</template>
<template v-slot:append>
<div class="text-right" style="width: 42px;">{{ settingsStore.settings.lshaped_screen_crop_y_position }}%</div>
</template>
</v-slider>
<div class="mt-5 ml-0">
<div class="d-flex align-center">
<span>拡大起点</span>
</div>
<div class="text-text-darken-1 mt-2" style="font-size: 13.5px;">
拡大率を変更したときに、どの位置を基準に拡大するかを設定します。
</div>
</div>
<v-radio-group class="zoom-origin-radio-group mt-3 ml-0" color="primary" inline hide-details
v-model="settingsStore.settings.lshaped_screen_crop_zoom_origin">
<v-radio label="左上" value="TopLeft"></v-radio>
<v-radio label="左下" value="BottomLeft"></v-radio>
<v-radio label="右上" value="TopRight"></v-radio>
<v-radio label="右下" value="BottomRight"></v-radio>
</v-radio-group>
</div>
</v-card>
</v-dialog>
</template>
<script lang="ts" setup>
import usePlayerStore from '@/stores/PlayerStore';
import useSettingsStore from '@/stores/SettingsStore';
const settingsStore = useSettingsStore();
const playerStore = usePlayerStore();
</script>
<style lang="scss">
.zoom-origin-radio-group .v-selection-control-group {
column-gap: 12px;
.v-label {
opacity: 1 !important;
}
}
</style>
<style lang="scss" scoped>
.shortcut-key {
display: inline-flex;
align-items: center;
justify-content: center;
flex-shrink: 0;
min-width: 32px;
min-height: 28px;
padding: 3px 8px;
border-radius: 5px;
background-color: rgb(var(--v-theme-background-lighten-2));
font-size: 14.5px;
text-align: center;
}
.shortcut-key-plus {
display: inline-block;
margin: 0px 5px;
flex-shrink: 0;
}
</style>
3 changes: 3 additions & 0 deletions client/src/components/Watch/Watch.vue
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
<WatchPanel :playback_mode="playback_mode" />
</main>
<KeyboardShortcutList :playback_mode="playback_mode" />
<LShapedScreenCropSettings />
</div>
</template>
<script lang="ts">
Expand All @@ -27,6 +28,7 @@ import { defineComponent, PropType } from 'vue';
import WatchHeader from '@/components/Watch/Header.vue';
import KeyboardShortcutList from '@/components/Watch/KeyboardShortcutList.vue';
import LShapedScreenCropSettings from '@/components/Watch/LShapedScreenCropSettings.vue';
import WatchNavigation from '@/components/Watch/Navigation.vue';
import WatchPanel from '@/components/Watch/Panel.vue';
import WatchPlayer from '@/components/Watch/Player.vue';
Expand All @@ -39,6 +41,7 @@ export default defineComponent({
name: 'Watch',
components: {
KeyboardShortcutList,
LShapedScreenCropSettings,
WatchHeader,
WatchNavigation,
WatchPanel,
Expand Down
5 changes: 5 additions & 0 deletions client/src/services/Settings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,11 @@ export interface IClientSettings {
// showed_panel_last_time: 同期無効
// selected_twitter_account_id: 同期無効
saved_twitter_hashtags: string[];
// lshaped_screen_crop_enabled: 同期無効
// lshaped_screen_crop_zoom_level: 同期無効
// lshaped_screen_crop_x_position: 同期無効
// lshaped_screen_crop_y_position: 同期無効
// lshaped_screen_crop_zoom_origin: 同期無効
pinned_channel_ids: string[];
panel_display_state: 'RestorePreviousState' | 'AlwaysDisplay' | 'AlwaysFold';
tv_panel_active_tab: 'Program' | 'Channel' | 'Comment' | 'Twitter';
Expand Down
21 changes: 21 additions & 0 deletions client/src/services/player/PlayerController.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1203,6 +1203,27 @@ class PlayerController {
}
});

// 設定パネルにL字画面のクロップ設定を表示するボタンを動的に追加する
this.player.template.settingOriginPanel.insertAdjacentHTML('beforeend', `
<div class="dplayer-setting-item dplayer-setting-lshaped-screen-crop">
<span class="dplayer-label">L字画面のクロップ設定</span>
<div class="dplayer-toggle">
<svg xmlns="http://www.w3.org/2000/svg" version="1.1" viewBox="0 0 32 32">
<path d="M22 16l-10.105-10.6-1.895 1.987 8.211 8.613-8.211 8.612 1.895 1.988 8.211-8.613z"></path>
</svg>
</div>
</div>
`);

// L字画面のクロップ設定モーダルを表示するボタンがクリックされたときのイベントハンドラーを登録
this.player.template.settingOriginPanel.querySelector('.dplayer-setting-lshaped-screen-crop')!.addEventListener('click', () => {
assert(this.player !== null);
// 設定パネルを閉じる
this.player.setting.hide();
// L字画面のクロップ設定モーダルを表示する
player_store.lshaped_screen_crop_settings_modal = true;
});

// 設定パネルにショートカット一覧を表示するボタンを動的に追加する
// スマホなどのタッチデバイスでは基本キーボードが使えないため、タッチデバイスの場合はボタンを表示しない
if (Utils.isTouchDevice() === false) {
Expand Down
3 changes: 3 additions & 0 deletions client/src/stores/PlayerStore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,9 @@ const usePlayerStore = defineStore('player', {
// キーボードショートカットの一覧のモーダルを表示するか
shortcut_key_modal: false,

// L字画面のクロップ設定のモーダルを表示するか
lshaped_screen_crop_settings_modal: false,

// ライブ視聴: 現在のライブストリームのステータス
// 既定で null (未視聴) とする
live_stream_status: null as 'Offline' | 'Standby' | 'ONAir' | 'Idling' | 'Restart' | null,
Expand Down
23 changes: 23 additions & 0 deletions client/src/stores/SettingsStore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,11 @@ export interface ILocalClientSettings extends IClientSettings {
showed_panel_last_time: boolean;
selected_twitter_account_id: number | null;
saved_twitter_hashtags: string[];
lshaped_screen_crop_enabled: boolean;
lshaped_screen_crop_zoom_level: number;
lshaped_screen_crop_x_position: number;
lshaped_screen_crop_y_position: number;
lshaped_screen_crop_zoom_origin: 'TopLeft' | 'TopRight' | 'BottomLeft' | 'BottomRight';
pinned_channel_ids: string[];
panel_display_state: 'RestorePreviousState' | 'AlwaysDisplay' | 'AlwaysFold';
tv_panel_active_tab: 'Program' | 'Channel' | 'Comment' | 'Twitter';
Expand Down Expand Up @@ -81,6 +86,19 @@ export const ILocalClientSettingsDefault: ILocalClientSettings = {
// 保存している Twitter のハッシュタグが入るリスト
saved_twitter_hashtags: [],

// ***** L字画面のクロップ設定 *****

// L字画面のクロップを有効にする (Default: 無効)
lshaped_screen_crop_enabled: false,
// L字画面のクロップの拡大率 (Default: 100%)
lshaped_screen_crop_zoom_level: 100,
// L字画面のクロップのX座標 (Default: 0%)
lshaped_screen_crop_x_position: 0,
// L字画面のクロップのY座標 (Default: 0%)
lshaped_screen_crop_y_position: 0,
// L字画面のクロップの拡大起点 (Default: 左上)
lshaped_screen_crop_zoom_origin: 'TopLeft',

// ***** 設定 → 全般 *****

// ピン留めしているチャンネルの ID (ex: gr011) が入るリスト
Expand Down Expand Up @@ -206,6 +224,11 @@ const SYNCABLE_SETTINGS_KEYS: (keyof IClientSettings)[] = [
// showed_panel_last_time: 同期無効
// selected_twitter_account_id: 同期無効
'saved_twitter_hashtags',
// lshaped_screen_crop_enabled: 同期無効
// lshaped_screen_crop_zoom_level: 同期無効
// lshaped_screen_crop_x_position: 同期無効
// lshaped_screen_crop_y_position: 同期無効
// lshaped_screen_crop_zoom_origin: 同期無効
'pinned_channel_ids',
'panel_display_state',
'tv_panel_active_tab',
Expand Down
5 changes: 5 additions & 0 deletions server/app/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,11 @@ class ClientSettings(BaseModel):
# showed_panel_last_time: 同期無効
# selected_twitter_account_id: 同期無効
saved_twitter_hashtags: list[str] = []
# lshaped_screen_crop_enabled: 同期無効
# lshaped_screen_crop_zoom_level: 同期無効
# lshaped_screen_crop_x_position: 同期無効
# lshaped_screen_crop_y_position: 同期無効
# lshaped_screen_crop_zoom_origin: 同期無効
pinned_channel_ids: list[str] = []
panel_display_state: Literal['RestorePreviousState', 'AlwaysDisplay', 'AlwaysFold'] = 'RestorePreviousState'
tv_panel_active_tab: Literal['Program', 'Channel', 'Comment', 'Twitter'] = 'Program'
Expand Down

0 comments on commit 93c5da9

Please sign in to comment.