--- /dev/null
+// OpenTween - Client of Twitter
+// Copyright (c) 2024 kim_upsilon (@kim_upsilon) <https://upsilo.net/~upsilon/>
+// All rights reserved.
+//
+// This file is part of OpenTween.
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 3 of the License, or (at your option)
+// any later version.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+// for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program. If not, see <http://www.gnu.org/licenses/>, or write to
+// the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
+// Boston, MA 02110-1301, USA.
+
+using Xunit;
+
+namespace OpenTween.Models
+{
+ public class StatusTextHistoryTest
+ {
+ [Fact]
+ public void Initialize_Test()
+ {
+ var history = new StatusTextHistory();
+ Assert.Single(history.Items);
+ Assert.Equal(new("", null), history.Items[0]);
+ Assert.Equal(0, history.HistoryIndex);
+ }
+
+ [Fact]
+ public void Back_NoItemsTest()
+ {
+ var history = new StatusTextHistory();
+ history.Back("@hoge aaa", (new TwitterStatusId("111"), "hoge"));
+ Assert.Single(history.Items);
+ Assert.Equal(new("@hoge aaa", (new TwitterStatusId("111"), "hoge")), history.Items[0]);
+ Assert.Equal(0, history.HistoryIndex);
+ }
+
+ [Fact]
+ public void Back_HasItemsTest()
+ {
+ var history = new StatusTextHistory();
+ history.SetLastItem("@hoge aaa", (new TwitterStatusId("111"), "hoge"));
+ history.AddLast();
+ history.Back("@foo bbb", (new TwitterStatusId("222"), "foo"));
+
+ Assert.Equal(2, history.Items.Count);
+ Assert.Equal(new("@hoge aaa", (new TwitterStatusId("111"), "hoge")), history.Items[0]);
+ Assert.Equal(new("@foo bbb", (new TwitterStatusId("222"), "foo")), history.Items[1]);
+ Assert.Equal(0, history.HistoryIndex);
+ }
+
+ [Fact]
+ public void Forward_NoItemsTest()
+ {
+ var history = new StatusTextHistory();
+ history.Forward("@hoge aaa", (new TwitterStatusId("111"), "hoge"));
+ Assert.Single(history.Items);
+ Assert.Equal(new("@hoge aaa", (new TwitterStatusId("111"), "hoge")), history.Items[0]);
+ Assert.Equal(0, history.HistoryIndex);
+ }
+
+ [Fact]
+ public void Forward_HasItemsTest()
+ {
+ var history = new StatusTextHistory();
+ history.SetLastItem("@hoge aaa", (new TwitterStatusId("111"), "hoge"));
+ history.AddLast();
+ history.Back("@foo bbb", (new TwitterStatusId("222"), "foo"));
+ history.Forward("@hoge aaa 123", (new TwitterStatusId("111"), "hoge"));
+
+ Assert.Equal(2, history.Items.Count);
+ Assert.Equal(new("@hoge aaa 123", (new TwitterStatusId("111"), "hoge")), history.Items[0]);
+ Assert.Equal(new("@foo bbb", (new TwitterStatusId("222"), "foo")), history.Items[1]);
+ Assert.Equal(1, history.HistoryIndex);
+ }
+
+ [Fact]
+ public void AddLast_Test()
+ {
+ var history = new StatusTextHistory();
+ history.SetLastItem("@hoge aaa", (new TwitterStatusId("111"), "hoge"));
+ history.AddLast();
+ Assert.Equal(2, history.Items.Count);
+ Assert.Equal(new("@hoge aaa", (new TwitterStatusId("111"), "hoge")), history.Items[0]);
+ Assert.Equal(new("", null), history.Items[1]);
+ Assert.Equal(1, history.HistoryIndex);
+ }
+
+ [Fact]
+ public void Peek_EmptyTest()
+ {
+ var history = new StatusTextHistory();
+ Assert.Null(history.Peek());
+ }
+
+ [Fact]
+ public void Peek_HasItemsTest()
+ {
+ var history = new StatusTextHistory();
+ history.SetLastItem("@hoge aaa", (new TwitterStatusId("111"), "hoge"));
+ history.AddLast();
+
+ Assert.Equal(new("@hoge aaa", (new TwitterStatusId("111"), "hoge")), history.Peek());
+ }
+ }
+}
--- /dev/null
+// OpenTween - Client of Twitter
+// Copyright (c) 2024 kim_upsilon (@kim_upsilon) <https://upsilo.net/~upsilon/>
+// All rights reserved.
+//
+// This file is part of OpenTween.
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 3 of the License, or (at your option)
+// any later version.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+// for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program. If not, see <http://www.gnu.org/licenses/>, or write to
+// the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
+// Boston, MA 02110-1301, USA.
+
+#nullable enable
+
+using System.Collections.Generic;
+
+namespace OpenTween.Models
+{
+ public class StatusTextHistory
+ {
+ public readonly record struct HistoryItem(
+ string Status,
+ (PostId StatusId, string ScreenName)? InReplyTo = null
+ );
+
+ internal IReadOnlyList<HistoryItem> Items
+ => this.items;
+
+ internal int HistoryIndex
+ => this.historyIndex;
+
+ private readonly List<HistoryItem> items = new();
+ private int historyIndex = 0;
+
+ public StatusTextHistory()
+ => this.items.Add(new(""));
+
+ public HistoryItem Back(string text, (PostId StatusId, string ScreenName)? inReplyTo)
+ {
+ if (!string.IsNullOrWhiteSpace(text))
+ this.items[this.historyIndex] = new(text, inReplyTo);
+
+ this.historyIndex -= 1;
+ if (this.historyIndex < 0)
+ this.historyIndex = 0;
+
+ return this.items[this.historyIndex];
+ }
+
+ public HistoryItem Forward(string text, (PostId StatusId, string ScreenName)? inReplyTo)
+ {
+ if (!string.IsNullOrWhiteSpace(text))
+ this.items[this.historyIndex] = new(text, inReplyTo);
+
+ this.historyIndex += 1;
+ if (this.historyIndex > this.items.Count - 1)
+ this.historyIndex = this.items.Count - 1;
+
+ return this.items[this.historyIndex];
+ }
+
+ public void SetLastItem(string text, (PostId StatusId, string ScreenName)? inReplyTo)
+ => this.items[this.items.Count - 1] = new(text, inReplyTo);
+
+ public void AddLast()
+ {
+ this.items.Add(new(""));
+ this.historyIndex = this.items.Count - 1;
+ }
+
+ public HistoryItem? Peek()
+ {
+ if (this.items.Count < 2)
+ return null;
+
+ return this.items[this.items.Count - 2];
+ }
+ }
+}
private readonly ThumbnailGenerator thumbGenerator;
/// <summary>発言履歴</summary>
- private readonly List<StatusTextHistory> history = new();
-
- /// <summary>発言履歴カレントインデックス</summary>
- private int hisIdx;
+ private readonly StatusTextHistory history = new();
// 発言投稿時のAPI引数(発言編集時に設定。手書きreplyでは設定されない)
PrevSearch,
}
- private readonly record struct StatusTextHistory(
- string Status,
- (PostId StatusId, string ScreenName)? InReplyTo = null
- );
-
private readonly HookGlobalHotkey hookGlobalHotkey;
public TweenMain(
this.recommendedStatusFooter = " [TWNv" + Regex.Replace(MyCommon.FileVersion.Replace(".", ""), "^0*", "") + "]";
- this.history.Add(new StatusTextHistory(""));
- this.hisIdx = 0;
this.inReplyTo = null;
// 各種ダイアログ設定
private void StatusTextHistoryBack()
{
- if (!string.IsNullOrWhiteSpace(this.StatusText.Text))
- this.history[this.hisIdx] = new StatusTextHistory(this.StatusText.Text, this.inReplyTo);
-
- this.hisIdx -= 1;
- if (this.hisIdx < 0)
- this.hisIdx = 0;
-
- var historyItem = this.history[this.hisIdx];
+ var historyItem = this.history.Back(this.StatusText.Text, this.inReplyTo);
this.inReplyTo = historyItem.InReplyTo;
this.StatusText.Text = historyItem.Status;
this.StatusText.SelectionStart = this.StatusText.Text.Length;
private void StatusTextHistoryForward()
{
- if (!string.IsNullOrWhiteSpace(this.StatusText.Text))
- this.history[this.hisIdx] = new StatusTextHistory(this.StatusText.Text, this.inReplyTo);
-
- this.hisIdx += 1;
- if (this.hisIdx > this.history.Count - 1)
- this.hisIdx = this.history.Count - 1;
-
- var historyItem = this.history[this.hisIdx];
+ var historyItem = this.history.Forward(this.StatusText.Text, this.inReplyTo);
this.inReplyTo = historyItem.InReplyTo;
this.StatusText.Text = historyItem.Status;
this.StatusText.SelectionStart = this.StatusText.Text.Length;
return;
}
- this.history[this.history.Count - 1] = new StatusTextHistory(this.StatusText.Text, this.inReplyTo);
+ this.history.SetLastItem(this.StatusText.Text, this.inReplyTo);
if (this.settings.Common.Nicoms)
{
this.inReplyTo = null;
this.StatusText.Text = "";
- this.history.Add(new StatusTextHistory(""));
- this.hisIdx = this.history.Count - 1;
+ this.history.AddLast();
if (!this.settings.Common.FocusLockToStatusText)
this.CurrentListView.Focus();
this.urlUndoBuffer = null;
ttl.Append("Ver:").Append(MyCommon.GetReadableVersion());
break;
case MyCommon.DispTitleEnum.Post:
- if (this.history != null && this.history.Count > 1)
- ttl.Append(this.history[this.history.Count - 2].Status.Replace("\r\n", " "));
+ if (this.history.Peek() is { } lastItem)
+ ttl.Append(lastItem.Status.Replace("\r\n", " "));
break;
case MyCommon.DispTitleEnum.UnreadRepCount:
ttl.AppendFormat(Properties.Resources.SetMainWindowTitleText1, this.statuses.MentionTab.UnreadCount + this.statuses.DirectMessageTab.UnreadCount);