From 4a744e8b294e3ff3bcdd03a69eb223969e744b7e Mon Sep 17 00:00:00 2001 From: Kimura Youichi Date: Sun, 27 Mar 2022 06:46:34 +0900 Subject: [PATCH] =?utf8?q?=E3=83=AA=E3=83=97=E3=83=A9=E3=82=A4=E6=99=82?= =?utf8?q?=E3=81=AB=E6=8A=95=E7=A8=BF=E6=AC=84=E3=81=AB=E5=85=A5=E5=8A=9B?= =?utf8?q?=E3=81=99=E3=82=8B=E3=83=86=E3=82=AD=E3=82=B9=E3=83=88=E3=81=AE?= =?utf8?q?=E7=94=9F=E6=88=90=E5=87=A6=E7=90=86=E3=82=92=E6=95=B4=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit --- OpenTween/Resources/ChangeLog.txt | 3 + OpenTween/Tween.cs | 303 ++++++++------------------------------ 2 files changed, 68 insertions(+), 238 deletions(-) diff --git a/OpenTween/Resources/ChangeLog.txt b/OpenTween/Resources/ChangeLog.txt index a36868cf..d4296ed6 100644 --- a/OpenTween/Resources/ChangeLog.txt +++ b/OpenTween/Resources/ChangeLog.txt @@ -8,10 +8,13 @@ - 高DPI環境で表示した場合により高解像度のプロフィール画像が取得されるようになります - リストのアイコンサイズを none に設定した場合、発言が選択されるまでプロフィール画像のダウンロードを行わなくなります * CHG: ツイートの投稿者とRTしたユーザーに関するメニュー項目を整理 + * CHG: DMが選択されている時は「@返信」「@返信ALL」のどちらも「DM送信」と同じ動作となるように変更 + * CHG: 複数のユーザー宛のリプライ時にツイートの先頭にピリオドを加える仕様を廃止 * FIX: 「Twitter API稼働状況」のリンク先を修正 (thx @kzlogos!) * FIX: 起動時に読み込まれた検索・リストタブでフォロー状態を表す色が反映されない不具合を修正 (thx @Hawklaver!) * FIX: 等幅フォント表示を有効にした場合に背景色の設定が全面に適用されない不具合を修正 (thx @StoutAmmo!) * FIX: 起動直後の時点で発言詳細欄の背景色設定が適用されていない不具合を修正 + * FIX: 自分のツイートに対する「@返信ALL」で自分宛のMentionが付かない不具合を修正 (thx @doug_lee42!) ==== Ver 2.5.0(2022/02/05) * NEW: アカウント追加時の認可URLを右クリックでコピー可能にしました diff --git a/OpenTween/Tween.cs b/OpenTween/Tween.cs index 4e0abdf3..fa763adb 100644 --- a/OpenTween/Tween.cs +++ b/OpenTween/Tween.cs @@ -2885,7 +2885,7 @@ namespace OpenTween switch (SettingManager.Common.ListDoubleClickAction) { case 0: - this.MakeReplyOrDirectStatus(); + this.MakeReplyText(); break; case 1: await this.FavoriteChange(true); @@ -3230,10 +3230,10 @@ namespace OpenTween } private void ReplyStripMenuItem_Click(object sender, EventArgs e) - => this.MakeReplyOrDirectStatus(false, true); + => this.MakeReplyText(); private void DMStripMenuItem_Click(object sender, EventArgs e) - => this.MakeReplyOrDirectStatus(false, false); + => this.MakeDirectMessageText(); private async Task DoStatusDelete() { @@ -5676,7 +5676,7 @@ namespace OpenTween ShortcutCommand.Create(Keys.Enter) .FocusedOn(FocusedControl.ListTab) - .Do(() => this.MakeReplyOrDirectStatus()), + .Do(() => this.MakeReplyText()), ShortcutCommand.Create(Keys.R) .FocusedOn(FocusedControl.ListTab) @@ -5765,13 +5765,13 @@ namespace OpenTween .Do(() => { }), ShortcutCommand.Create(Keys.Control | Keys.R) - .Do(() => this.MakeReplyOrDirectStatus(isAuto: false, isReply: true)), + .Do(() => this.MakeReplyText()), ShortcutCommand.Create(Keys.Control | Keys.D) .Do(() => this.DoStatusDelete()), ShortcutCommand.Create(Keys.Control | Keys.M) - .Do(() => this.MakeReplyOrDirectStatus(isAuto: false, isReply: false)), + .Do(() => this.MakeDirectMessageText()), ShortcutCommand.Create(Keys.Control | Keys.S) .Do(() => this.FavoriteChange(favAdd: true)), @@ -6014,7 +6014,7 @@ namespace OpenTween .Do(() => this.GoSamePostToAnotherTab(left: true)), ShortcutCommand.Create(Keys.Control | Keys.Shift | Keys.R) - .Do(() => this.MakeReplyOrDirectStatus(isAuto: false, isReply: true, isAll: true)), + .Do(() => this.MakeReplyText(atAll: true)), ShortcutCommand.Create(Keys.Control | Keys.Shift | Keys.C, Keys.Control | Keys.Shift | Keys.Insert) .Do(() => this.CopyIdUri()), @@ -7408,250 +7408,77 @@ namespace OpenTween this.SaveConfigsTabs(); } - private void MakeReplyOrDirectStatus(bool isAuto = true, bool isReply = true, bool isAll = false) + private void MakeDirectMessageText() { - // isAuto:true=先頭に挿入、false=カーソル位置に挿入 - // isReply:true=@,false=DM - if (!this.StatusText.Enabled) return; - if (!this.ExistCurrentPost) return; + var selectedPosts = this.CurrentTab.SelectedPosts; + if (selectedPosts.Length > 1) + return; - var tab = this.CurrentTab; - var selectedPosts = tab.SelectedPosts; + var post = selectedPosts.Single(); + var text = $"D {post.ScreenName} {this.StatusText.Text}"; - // 複数あてリプライはReplyではなく通常ポスト - // ↑仕様変更で全部リプライ扱いでOK(先頭ドット付加しない) - // 090403暫定でドットを付加しないようにだけ修正。単独と複数の処理は統合できると思われる。 - // 090513 all @ replies 廃止の仕様変更によりドット付加に戻し(syo68k) + this.inReplyTo = null; + this.StatusText.Text = text; + this.StatusText.SelectionStart = text.Length; + this.StatusText.Focus(); + } - if (selectedPosts.Length > 0) + private void MakeReplyText(bool atAll = false) + { + var selectedPosts = this.CurrentTab.SelectedPosts; + if (selectedPosts.Any(x => x.IsDm)) { - // アイテムが1件以上選択されている - if (selectedPosts.Length == 1 && !isAll && this.ExistCurrentPost) - { - var post = selectedPosts.Single(); + this.MakeDirectMessageText(); + return; + } - // 単独ユーザー宛リプライまたはDM - if ((tab.TabType == MyCommon.TabUsageType.DirectMessage && isAuto) || (!isAuto && !isReply)) - { - // ダイレクトメッセージ - this.inReplyTo = null; - this.StatusText.Text = "D " + post.ScreenName + " " + this.StatusText.Text; - this.StatusText.SelectionStart = this.StatusText.Text.Length; - this.StatusText.Focus(); - return; - } - if (MyCommon.IsNullOrEmpty(this.StatusText.Text)) - { - // 空の場合 - var inReplyToStatusId = post.RetweetedId ?? post.StatusId; - var inReplyToScreenName = post.ScreenName; - this.inReplyTo = (inReplyToStatusId, inReplyToScreenName); + if (selectedPosts.Length == 1) + { + var post = selectedPosts.Single(); + var inReplyToStatusId = post.RetweetedId ?? post.StatusId; + var inReplyToScreenName = post.ScreenName; + this.inReplyTo = (inReplyToStatusId, inReplyToScreenName); + } + else + { + this.inReplyTo = null; + } - // ステータステキストが入力されていない場合先頭に@ユーザー名を追加する - this.StatusText.Text = "@" + post.ScreenName + " "; - } - else - { - // 何か入力済の場合 + var selfScreenName = this.tw.Username; + var targetScreenNames = new List(); + foreach (var post in selectedPosts) + { + if (post.ScreenName != selfScreenName) + targetScreenNames.Add(post.ScreenName); - if (isAuto) - { - // 1件選んでEnter or DoubleClick - if (this.StatusText.Text.Contains("@" + post.ScreenName + " ")) - { - if (this.inReplyTo?.ScreenName == post.ScreenName) - { - // 返信先書き換え - var inReplyToStatusId = post.RetweetedId ?? post.StatusId; - var inReplyToScreenName = post.ScreenName; - this.inReplyTo = (inReplyToStatusId, inReplyToScreenName); - } - return; - } - if (!this.StatusText.Text.StartsWith("@", StringComparison.Ordinal)) - { - // 文頭@以外 - if (this.StatusText.Text.StartsWith(". ", StringComparison.Ordinal)) - { - // 複数リプライ - this.inReplyTo = null; - this.StatusText.Text = this.StatusText.Text.Insert(2, "@" + post.ScreenName + " "); - } - else - { - // 単独リプライ - var inReplyToStatusId = post.RetweetedId ?? post.StatusId; - var inReplyToScreenName = post.ScreenName; - this.inReplyTo = (inReplyToStatusId, inReplyToScreenName); - this.StatusText.Text = "@" + post.ScreenName + " " + this.StatusText.Text; - } - } - else - { - // 文頭@ - // 複数リプライ - this.inReplyTo = null; - this.StatusText.Text = ". @" + post.ScreenName + " " + this.StatusText.Text; - } - } - else - { - // 1件選んでCtrl-Rの場合(返信先操作せず) - var sidx = this.StatusText.SelectionStart; - var id = "@" + post.ScreenName + " "; - if (sidx > 0) - { - if (this.StatusText.Text.Substring(sidx - 1, 1) != " ") - { - id = " " + id; - } - } - this.StatusText.Text = this.StatusText.Text.Insert(sidx, id); - sidx += id.Length; - this.StatusText.SelectionStart = sidx; - this.StatusText.Focus(); - return; - } - } - } - else + if (atAll) { - // 複数リプライ - if (!isAuto && !isReply) return; - - // C-S-rか、複数の宛先を選択中にEnter/DoubleClick/C-r/C-S-r - - if (isAuto) + foreach (var (_, screenName) in post.ReplyToList) { - // Enter or DoubleClick - - var sTxt = this.StatusText.Text; - if (!sTxt.StartsWith(". ", StringComparison.Ordinal)) - { - sTxt = ". " + sTxt; - this.inReplyTo = null; - } - foreach (var post in selectedPosts) - { - if (!sTxt.Contains("@" + post.ScreenName + " ")) - sTxt = sTxt.Insert(2, "@" + post.ScreenName + " "); - } - this.StatusText.Text = sTxt; + if (screenName != selfScreenName) + targetScreenNames.Add(screenName); } - else - { - // C-S-r or C-r - - if (selectedPosts.Length > 1) - { - // 複数ポスト選択 - - var ids = ""; - var sidx = this.StatusText.SelectionStart; - foreach (var post in selectedPosts) - { - if (!ids.Contains("@" + post.ScreenName + " ") && post.UserId != this.tw.UserId) - { - ids += "@" + post.ScreenName + " "; - } - if (isAll) - { - foreach (var (_, screenName) in post.ReplyToList) - { - if (!ids.Contains("@" + screenName + " ") && - !screenName.Equals(this.tw.Username, StringComparison.CurrentCultureIgnoreCase)) - { - var m = Regex.Match(post.TextFromApi, "[@@](?" + screenName + ")([^a-zA-Z0-9]|$)", RegexOptions.IgnoreCase); - if (m.Success) - ids += "@" + m.Result("${id}") + " "; - else - ids += "@" + screenName + " "; - } - } - } - } - if (ids.Length == 0) return; - if (!this.StatusText.Text.StartsWith(". ", StringComparison.Ordinal)) - { - this.inReplyTo = null; - this.StatusText.Text = ". " + this.StatusText.Text; - sidx += 2; - } - if (sidx > 0) - { - if (this.StatusText.Text.Substring(sidx - 1, 1) != " ") - { - ids = " " + ids; - } - } - this.StatusText.Text = this.StatusText.Text.Insert(sidx, ids); - sidx += ids.Length; - this.StatusText.SelectionStart = sidx; - this.StatusText.Focus(); - return; - } - else - { - // 1件のみ選択のC-S-r(返信元付加する可能性あり) + } + } - var ids = ""; - var sidx = this.StatusText.SelectionStart; - var post = selectedPosts.Single(); - if (!ids.Contains("@" + post.ScreenName + " ") && post.UserId != this.tw.UserId) - { - ids += "@" + post.ScreenName + " "; - } - foreach (var (_, screenName) in post.ReplyToList) - { - if (!ids.Contains("@" + screenName + " ") && - !screenName.Equals(this.tw.Username, StringComparison.CurrentCultureIgnoreCase)) - { - var m = Regex.Match(post.TextFromApi, "[@@](?" + screenName + ")([^a-zA-Z0-9]|$)", RegexOptions.IgnoreCase); - if (m.Success) - ids += "@" + m.Result("${id}") + " "; - else - ids += "@" + screenName + " "; - } - } - if (!MyCommon.IsNullOrEmpty(post.RetweetedBy)) - { - if (!ids.Contains("@" + post.RetweetedBy + " ") && post.RetweetedByUserId != this.tw.UserId) - { - ids += "@" + post.RetweetedBy + " "; - } - } - if (ids.Length == 0) return; - if (MyCommon.IsNullOrEmpty(this.StatusText.Text)) - { - // 未入力の場合のみ返信先付加 - var inReplyToStatusId = post.RetweetedId ?? post.StatusId; - var inReplyToScreenName = post.ScreenName; - this.inReplyTo = (inReplyToStatusId, inReplyToScreenName); - - this.StatusText.Text = ids; - this.StatusText.SelectionStart = ids.Length; - this.StatusText.Focus(); - return; - } + if (this.inReplyTo != null) + { + var (_, screenName) = this.inReplyTo.Value; + if (screenName == selfScreenName) + targetScreenNames.Insert(0, screenName); + } - if (sidx > 0) - { - if (this.StatusText.Text.Substring(sidx - 1, 1) != " ") - { - ids = " " + ids; - } - } - this.StatusText.Text = this.StatusText.Text.Insert(sidx, ids); - sidx += ids.Length; - this.StatusText.SelectionStart = sidx; - this.StatusText.Focus(); - return; - } - } - } - this.StatusText.SelectionStart = this.StatusText.Text.Length; - this.StatusText.Focus(); + var text = this.StatusText.Text; + foreach (var screenName in targetScreenNames.AsEnumerable().Reverse()) + { + var atText = $"@{screenName} "; + if (!text.Contains(atText)) + text = atText + text; } + + this.StatusText.Text = text; + this.StatusText.SelectionStart = text.Length; + this.StatusText.Focus(); } private void ListTab_MouseUp(object sender, MouseEventArgs e) @@ -8097,7 +7924,7 @@ namespace OpenTween } private void ReplyAllStripMenuItem_Click(object sender, EventArgs e) - => this.MakeReplyOrDirectStatus(false, true, true); + => this.MakeReplyText(atAll: true); private void IDRuleMenuItem_Click(object sender, EventArgs e) { -- 2.11.0