-
Notifications
You must be signed in to change notification settings - Fork 309
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
ツールバーのボタンをカスタマイズ可能にする #489
Conversation
This reverts commit fd3c3d9.
タイトルバーを上に戻しました!まあプレビュー中であることはすでにわかると思うので、これで良さそうですね...!
設定ボタンなどを押したときに閉じれてしまうのは盲点でした... 2の挙動の方がユーザー的には好ましいのかもしれないですが、若干気持ち悪いという点があります。
少し苦戦しましたが、 #472 を元に追加しました!(backgroundで定義したデフォルト値を取ってくる方法がいまいちわからず苦戦しました、先人の方、ありがとうございます...!) 加えて、レビューには書かれていませんが、すべてのボタンを消したときの挙動を改善し、 また、ダークテーマ時適用時の色が変になる現象を解消しました(デフォルトテーマ時の色も若干変更しています)。
あと、データ構造が若干冗長(?)だったので、整理しました。これによって、一度config.jsonの |
2d5a6ee
to
b6a483b
Compare
うーん・・・比較的ロジックが簡単そうなので、1でお願いします!! このプルリクエストで組み込む内容じゃないですが、そもそもダイアログを開いたときはメニューボタンを押せなくなるようにしたほうが良い気がしてきました。 |
適用しました!
確かにそうかもしれませんね…. |
# Conflicts: # src/components/MenuBar.vue # src/electron/preload.ts # src/type/ipc.d.ts
コンフリクトを解消し、#518 のおかげで、不要になった部分を削除したり、一部文言の統一をしたりしました。 |
|
なるほど、少し切り分けてみますね |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@Hiroshiba さんが見られたようですが全体を見て,特に気になった部分をコメントしました.
正直,あまり正しいことを言っている自信がないのでダブルチェックして頂けると助かります...
export type ToolbarButtonsType = | ||
| "連続再生" | ||
| "再生" | ||
| "音声書き出し" | ||
| "一つだけ書き出し" | ||
| "停止" | ||
| "元に戻す" | ||
| "やり直す" | ||
| "テキスト読み込み" | ||
| "空白"; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
識別子とテキストの分離をした方が良いと思います.
GET_TOOLBAR_SETTING({ commit }) { | ||
const newData = window.electron.toolbarSetting(); | ||
newData.then((toolbarSetting) => { | ||
commit("SET_TOOLBAR_SETTING", { toolbarSetting }); | ||
}); | ||
}, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
非同期に処理を行うActionなので,Promiseをreturnするかasync functionで書き,commitされるまで待てるようにしておきましょう.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
確かに、仰る通りなのですが、他のactionが同じような形だったのであまり気にしていませんでした。
修正してみようかと思います。
SET_TOOLBAR_SETTING({ commit }, { data }: { data: ToolbarSetting }) { | ||
const newData = window.electron.toolbarSetting(data); | ||
newData.then((toolbarSetting) => { | ||
commit("SET_TOOLBAR_SETTING", { toolbarSetting }); | ||
}); | ||
}, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
非同期に処理を行うActionなので,Promiseをreturnするかasync functionで書き,commitされるまで待てるようにしておきましょう.
// 配列の比較は出来ないので、文字列として結合したものを比較する | ||
const changedOrNotFlag = computed(() => { | ||
const nowSetting = store.state.toolbarSetting; | ||
return toolbarButtons.value.join("") !== nowSetting.join(""); | ||
}); | ||
const defaultOrNotFlag = computed(() => { | ||
return toolbarButtons.value.join("") !== defaultSetting.join(""); | ||
}); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
普通に比較してしまってもいいと思います.
a.length == b.length && a.every((e, i) => e == b[i])
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
おっと、everyを使う手法は気づきませんでした。
そちらの方がきれいだと思うので、そちらで書き直してみたいと思います。
const usableButtons = [ | ||
{ | ||
label: "連続再生", | ||
desc: "選択されているテキスト以降のすべてのテキストを読み上げます。", | ||
}, | ||
{ | ||
label: "再生", | ||
desc: "選択されているテキストを読み上げます。", | ||
}, | ||
{ | ||
label: "停止", | ||
desc: "テキストが読み上げられているときに、それを止めます。", | ||
}, | ||
{ | ||
label: "音声書き出し", | ||
desc: "入力されているすべてのテキストの読み上げを音声ファイルに書き出します。", | ||
}, | ||
{ | ||
label: "一つだけ書き出し", | ||
desc: "選択されているテキストの読み上げを音声ファイルに書き出します。", | ||
}, | ||
{ | ||
label: "元に戻す", | ||
desc: "操作を一つ戻します。", | ||
}, | ||
{ | ||
label: "やり直す", | ||
desc: "元に戻した操作をやり直します。", | ||
}, | ||
{ | ||
label: "テキスト読み込み", | ||
desc: "テキストファイル(.txt)を読み込みます。", | ||
}, | ||
{ | ||
label: "空白", | ||
desc: "これはボタンではありません。レイアウトの調整に使います。また、実際には表示されません。", | ||
}, | ||
]; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
findが多いので識別子とテキストの分離をした方が良さそうです
|
||
type ButtonContent = | ||
| { | ||
text: ToolbarButtonsType; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ToolButtonsType
を表示するテキストそのものにしているため,テキストだけを変更したいときにも状態のマイグレーションが必要になってしまいます.(表示の為の要素がstateの中に混在してしまっています).
代わりに,そのボタンの機能ごとにタグを付けて管理してはどうでしょうか?(識別子とテキストの分離)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
なるほど、確かに言われてみれば、テキストだけを変更したい時を考えていませんでした。
識別子化は非常に良い解決策だと思うので、対応に当たりたいと思います。
const usableButtons: ButtonContent[] = [ | ||
{ | ||
text: "連続再生", | ||
click: playContinuously, | ||
disable: uiLocked, | ||
}, | ||
{ | ||
text: "再生", | ||
click: play, | ||
disable: computed(() => !activeAudioKey.value || uiLocked.value), | ||
}, | ||
{ | ||
text: "停止", | ||
click: stop, | ||
disable: computed( | ||
() => !nowPlayingContinuously.value && !nowPlaying.value | ||
), | ||
}, | ||
{ | ||
text: "音声書き出し", | ||
click: generateAndSaveAllAudio, | ||
disable: uiLocked, | ||
}, | ||
{ | ||
text: "一つだけ書き出し", | ||
click: generateAndSaveOneAudio, | ||
disable: computed(() => !activeAudioKey.value || uiLocked.value), | ||
}, | ||
{ | ||
text: "元に戻す", | ||
click: undo, | ||
disable: computed(() => !canUndo.value || uiLocked.value), | ||
}, | ||
{ | ||
text: "やり直す", | ||
click: redo, | ||
disable: computed(() => !canRedo.value || uiLocked.value), | ||
}, | ||
{ | ||
text: "テキスト読み込み", | ||
click: importTextFile, | ||
disable: uiLocked, | ||
}, | ||
]; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
textもcomputedにすれば,連続再生ボタンを連続再生停止の為にも使えます.
また,ツールバーに配置可能なactionの多くはHotKeyでも操作可能な処理が多いと思うので,その辺りと処理を纏めてactionを作ったり,disableをgetterで返したりするstoreを作ってしまってもいいかもしれません.
もっとも,ホットキーで使用可能な操作とツールバーで使用可能な操作が真に等しいかはもう少し議論すべきでしょうから,安易に纏めずにここに書き下しても構わないと思います.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
textもcomputedにすれば
確かに、これを機に再生と停止を同じボタンにまとめてしまうのは良いと思いました。
そうすれば、上のレビューであったcontinuouslyFlag
の利用をしなくて済むので、複雑度が下がりそうです。
ただ、このPR内で再生と停止をまとめてしまっていいかが微妙な気がします。
また、ボタンカスタマイズの時点で、再生と停止の両方を行えるボタンであることを示すことが難しいような気もしています。
何かいい方法はないですかね...?
ツールバーに配置可能なactionの多くはHotKeyでも操作可能な処理
actionにまとめてしまう感じのことは、WITH_DIALOG
系の処理で一度行っていますが、それ以外はこれ以上まとめられないような気がしています。getterを増やすのは良いかもと思いました。ちょっと検討してみます。
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ボタンカスタマイズの時点で、再生と停止の両方を行えるボタンであることを示すことが難しいような気もしています。
UIについて私は詳しくないので素人なのですが,押してみれば分かりますしこれまで使っていた人が最初見た時に混乱する程度でしょうか.特に記載を行わなくても問題はなさそうな気もしますが@Hiroshiba さんに意見を貰いたいです.
それとは別に今気づいたのですが,ContinuslyフラグをAudioStateに置くべきだと思いました.どちらにしても現在の実装ではShift+Space等の別経路で連続再生したときに,連続再生したか単体再生したかHeaderBarでは判別ができないからです.
とはいっても今の実装では,STOP_AUDIOを叩いてもSTOP_CONTINUOUSLY_AUDIOを叩いてもどちらでも停止してくれるようなので分岐を間違えてもバグにはないようです.STOP_CONTINUOUSLY_AUDIOだけ叩いていても問題にはならないのですが...
ツールバーに配置可能なactionの多くはHotKeyでも操作可能な処理
ショートカットキーは一部を除いてコンポーネントに所属しないグローバルな操作なのでショートカットキーの多くはactionとして記載でき,ツールバーにも置けるかなと思いましたがこのPRでする必要は特にないと思いました.testablityが改善しそうだったので提案しましたが忙しいならこのままでも構わないと思います.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
再生と停止を同じボタンにするのは別機能なので、とりあえずこのPRではしない方針で良いと思います。
UI上もそこまで大きな問題ではないので、要望が来るまではまあ良いかなと。
別経路で連続再生したときに,連続再生したか単体再生したかHeaderBarでは判別ができない
こちら目からウロコでした。見逃していました・・・レビュー感謝です。
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ボタンカスタマイズの時点で、再生と停止の両方を行えるボタンであることを示すことが難しいような気もしています。
押してみれば分かりますし
確かに、プレビュー時点で押せば表記が切り替わるみたいな挙動をさせるのは良いと思いました。
ただ、やはり再生(連続再生)と停止のボタン統合は別PRで行うべきな気がします。
一旦切り出したいところですね。
ContinuslyフラグをAudioStateに置くべき
おっと、この問題は気づきませんでした...(私がボイボにおいてほとんどホットキーを使わないので、そこまで頭が回っていませんでした...)
この問題を解決する(continuslyをstateに持っていく)ついでに、ショートカットキーの多くをactionに移行するというのはありな気がします。
ただ、一部の例外を置いておくなどはそれはそれで気持ち悪いような気もしますが....
どちらにせよ、このPRの規模が大きくなる一方な気がするので、やるならば別PRへの切り出しが必要そうです。
STOP_CONTINUOUSLY_AUDIOだけ叩いていても問題にはならないのですが...
(もうSTOP_CONTINUOUSLY_AUDIOをSTOP_AUDIOと統合してもいいんじゃないかなって個人的には思います...)
text: null, | ||
}; | ||
} else { | ||
return usableButtons.find((b) => b.text === button) as ButtonContent; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
タグで管理し,プロパティでアクセスする方が明示的です.
(このコードだと,as ButtonContent
でundefinedableを潰していますが, オブジェクトならそのプロパティが存在することを型レベルで強制できます.)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
型レベルで強制できる、確かに仰る通りです。
findの使い過ぎは私も少し感じていたので、オブジェクト化を試みようと思います。
<q-radio | ||
v-if="button === '空白'" | ||
v-model="selectedButton" | ||
size="0" | ||
:val="button" | ||
:label="button" | ||
:class=" | ||
(selectedButton === button | ||
? 'radio-space-selected' | ||
: 'radio-space') + ' text-no-wrap q-mr-sm' | ||
" | ||
><q-tooltip | ||
:delay="500" | ||
anchor="center left" | ||
self="center right" | ||
transition-show="jump-left" | ||
transition-hide="jump-right" | ||
>{{ | ||
usableButtons.find((v) => v.label === button).desc | ||
}}</q-tooltip | ||
></q-radio | ||
> | ||
<q-radio | ||
v-else | ||
v-model="selectedButton" | ||
size="0" | ||
:val="button" | ||
:label="button" | ||
:class=" | ||
(selectedButton === button ? 'radio-selected' : 'radio') + | ||
' text-no-wrap text-bold text-display q-mr-sm' | ||
" | ||
><q-tooltip | ||
:delay="500" | ||
anchor="center left" | ||
self="center right" | ||
transition-show="jump-left" | ||
transition-hide="jump-right" | ||
>{{ | ||
usableButtons.find((v) => v.label === button).desc | ||
}}</q-tooltip | ||
></q-radio | ||
> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
空白とそれ以外のボタンの違いはclassとテキストだけのようなので,v-ifで空白を特殊化するよりもclassをButtonsに持たせたりclassの部分で特殊化する方が短くなりそうです.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
三項演算子が増えそうで、ちょっとコードの可読性が落ちそうだったので手を付けていなかったのですが、仰る通りそれよりもコードを縮める方がよいかもしれません。
少し検討してみます。
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
レビューしてみました。
型に関して気になったところがあったのでコメントしました。
GENERATE_AND_SAVE_ALL_AUDIO_WITH_DIALOG: { | ||
action(payload: { | ||
$q: QVueGlobals; | ||
saveAllResultDialog: unknown; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ここの型は typeof SaveAllResultDialog
か の方がいいかもしれません。DefineComponent
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ここをDefineComponentにしなかったのは、型の調製がとてつもなくしんどかったからです(DefineComponentに渡すgenericsの引数まで合わせないと型エラーになってしまうので)
何かいい方法があればいいのですが、うまくいきそうにないので、この旨をコメントとして残しておくべきかなとは思いました。
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
DefineComponentに渡すgenericsの引数まで合わせないと型エラーになってしまう
おっと…これは確認不足でした。
なるほど、であれば確かにDefineComponentは使えなさそうですね…。
defaultSetting.push(...setting); | ||
}); | ||
|
||
const usableButtons = [ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
明示的に型を付けた方がいいかもしれません。
ちょっと、PRの規模が大きすぎるのと、同時にレビューでの改善点もかなりあるので、細分化してPRを作り直そうかと思います。 一旦closeしたいと思うのですが、どうでしょうか...? |
良いと思います! |
一旦クローズします! |
内容
題の通りです
※先に #490 を見てください。関連 Issue
close #462
スクリーンショット・動画など
その他
メニューバーの機能をコピペしてる部分があるので、それをどこか機能関数をまとめたファイルなどにまとめたい感じがあります。