Skip to content

Commit 0d4475d

Browse files
feat: 編集中のプロジェクトを表示できるように
1 parent eee78f4 commit 0d4475d

4 files changed

Lines changed: 164 additions & 48 deletions

File tree

src/YmmRPC/Settings/YmmRpcSettings.cs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,12 @@ public bool CustomRpcEnabled
2525
set => SetField(ref field, value);
2626
}
2727

28+
public bool IsShowProject
29+
{
30+
get;
31+
set => SetField(ref field, value);
32+
} = true;
33+
2834
public string CustomRpcDetails
2935
{
3036
get;
@@ -100,6 +106,5 @@ private void SetField<T>(ref T field, T value, [CallerMemberName] string? proper
100106
if (EqualityComparer<T>.Default.Equals(field, value)) return;
101107
field = value;
102108
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
103-
YmmRpcPlugin.RequestUpdate();
104109
}
105110
}

src/YmmRPC/Settings/YmmRpcSettingsView.xaml

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -28,16 +28,16 @@
2828
Value="{Binding Source={x:Static local:YmmRpcSettings.Default}, Path=IsEnabled, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>
2929
</Grid>
3030

31-
<!-- <Grid> -->
32-
<!-- <Grid.ColumnDefinitions> -->
33-
<!-- <ColumnDefinition Width="200"/> -->
34-
<!-- <ColumnDefinition Width="*"/> -->
35-
<!-- </Grid.ColumnDefinitions> -->
36-
<!-- <Label Content="プロジェクト名を表示"/> -->
37-
<!-- <c:ToggleSlider Grid.Column="1" -->
38-
<!-- HorizontalAlignment="Right" -->
39-
<!-- Value="{Binding Source={x:Static local:YmmRpcSettings.Default}, Path=IsShowProject, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/> -->
40-
<!-- </Grid> -->
31+
<Grid>
32+
<Grid.ColumnDefinitions>
33+
<ColumnDefinition Width="200"/>
34+
<ColumnDefinition Width="*"/>
35+
</Grid.ColumnDefinitions>
36+
<Label Content="プロジェクト名を表示"/>
37+
<c:ToggleSlider Grid.Column="1"
38+
HorizontalAlignment="Right"
39+
Value="{Binding Source={x:Static local:YmmRpcSettings.Default}, Path=IsShowProject, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>
40+
</Grid>
4141

4242
<Grid>
4343
<GroupBox Header="YMM RPC プラグインについて" HorizontalAlignment="Stretch" Margin="8">

src/YmmRPC/YmmRPC.csproj

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,15 @@
99
</PropertyGroup>
1010

1111
<ItemGroup>
12-
<Reference Include="YukkuriMovieMaker.Plugin" HintPath="..\..\libs\YukkuriMovieMaker.Plugin.dll" Private="true" />
13-
<Reference Include="YukkuriMovieMaker.Controls" HintPath="..\..\libs\YukkuriMovieMaker.Controls.dll" Private="true" />
14-
</ItemGroup>
15-
16-
<ItemGroup>
12+
<Reference Include="YukkuriMovieMaker.Plugin" HintPath="..\..\libs\YukkuriMovieMaker.Plugin.dll" Private="false">
13+
<ExcludeAssets>runtime</ExcludeAssets>
14+
</Reference>
15+
<Reference Include="YukkuriMovieMaker.Controls" HintPath="..\..\libs\YukkuriMovieMaker.Controls.dll" Private="false">
16+
<ExcludeAssets>runtime</ExcludeAssets>
17+
</Reference>
18+
1719
<PackageReference Include="DiscordRichPresence" Version="1.2.1.24" />
20+
1821
<PackageReference Include="Costura.Fody" Version="5.7.0">
1922
<PrivateAssets>all</PrivateAssets>
2023
</PackageReference>

src/YmmRPC/YmmRpc.cs

Lines changed: 140 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
using System.Diagnostics;
2+
using System.IO;
3+
using System.Reflection;
24
using System.Windows;
35
using DiscordRPC;
46
using DiscordRPC.Logging;
@@ -13,14 +15,15 @@ public class YmmRpcPlugin : IPlugin, IDisposable
1315
{
1416
public string Name => "YMM-RPC";
1517

16-
private static readonly string ClientId = IsLiteEdition() ? "1455192227734098075" : "1353376132732420136";
17-
private const string Version = "0.3.0";
18+
private const string ClientIdLite = "1455192227734098075";
19+
private const string ClientIdNormal = "1353376132732420136";
20+
private const string Version = "0.3.1";
1821
private const int UpdateIntervalMs = 15000;
1922

2023
private static DiscordRpcClient? _client;
2124
private static Timer? _updateTimer;
2225
private static DateTime _startTime;
23-
private static volatile bool _updateRequested;
26+
private static bool? _isLiteEdition;
2427
private bool _disposed;
2528

2629
public YmmRpcPlugin()
@@ -34,7 +37,9 @@ private static void InitializeClient()
3437
{
3538
if (_client is { IsDisposed: false }) return;
3639

37-
_client = new DiscordRpcClient(ClientId)
40+
var clientId = GetIsLiteEdition() ? ClientIdLite : ClientIdNormal;
41+
42+
_client = new DiscordRpcClient(clientId)
3843
{
3944
Logger = new ConsoleLogger { Level = LogLevel.Warning }
4045
};
@@ -43,21 +48,34 @@ private static void InitializeClient()
4348
_client.OnError += (_, e) => Console.WriteLine($"[YMM-RPC] Error: {e.Message}");
4449

4550
_client.Initialize();
46-
UpdatePresence();
4751
}
4852

4953
private static void StartUpdateTimer()
5054
{
5155
_updateTimer?.Dispose();
5256
_updateTimer = new Timer(_ =>
5357
{
54-
if (!_updateRequested) return;
55-
_updateRequested = false;
56-
UpdatePresence();
58+
SafeUpdatePresence();
5759
}, null, UpdateIntervalMs, UpdateIntervalMs);
5860
}
5961

60-
public static void RequestUpdate() => _updateRequested = true;
62+
private static void SafeUpdatePresence()
63+
{
64+
try
65+
{
66+
var dispatcher = Application.Current?.Dispatcher;
67+
if (dispatcher == null)
68+
{
69+
UpdatePresence();
70+
return;
71+
}
72+
dispatcher.Invoke(UpdatePresence);
73+
}
74+
catch (Exception ex)
75+
{
76+
Console.WriteLine($"[YMM-RPC] Update error: {ex.Message}");
77+
}
78+
}
6179

6280
private static void UpdatePresence()
6381
{
@@ -71,19 +89,77 @@ private static void UpdatePresence()
7189
return;
7290
}
7391

74-
var presence = settings.CustomRpcEnabled
75-
? BuildCustomPresence(settings)
92+
var presence = settings.CustomRpcEnabled
93+
? BuildCustomPresence(settings)
7694
: BuildDefaultPresence();
7795

7896
_client.SetPresence(presence);
7997
}
8098

99+
private static string? GetCurrentProjectName()
100+
{
101+
try
102+
{
103+
var mainWindow = Application.Current?.Windows
104+
.OfType<Window>()
105+
.FirstOrDefault(w =>
106+
string.Equals(
107+
w.GetType().FullName,
108+
"YukkuriMovieMaker.Views.MainView",
109+
StringComparison.Ordinal));
110+
111+
if (mainWindow?.DataContext == null) return null;
112+
113+
var vmType = mainWindow.DataContext.GetType();
114+
var filePathProp = vmType.GetProperty("ProjectFilePath", BindingFlags.Public | BindingFlags.Instance);
115+
116+
if (filePathProp == null) return null;
117+
118+
var filePathValue = filePathProp.GetValue(mainWindow.DataContext);
119+
var filePath = ExtractValue<string>(filePathValue);
120+
121+
return string.IsNullOrEmpty(filePath) ? null : Path.GetFileNameWithoutExtension(filePath);
122+
}
123+
catch
124+
{
125+
return null;
126+
}
127+
}
128+
129+
private static T? ExtractValue<T>(object? obj)
130+
{
131+
if (obj == null) return default;
132+
if (obj is T directValue) return directValue;
133+
134+
var valueProperty = obj.GetType().GetProperty("Value", BindingFlags.Public | BindingFlags.Instance);
135+
if (valueProperty == null) return default;
136+
137+
var innerValue = valueProperty.GetValue(obj);
138+
if (innerValue is T typedValue) return typedValue;
139+
return innerValue != null ? ExtractValue<T>(innerValue) : default;
140+
}
141+
81142
private static RichPresence BuildDefaultPresence()
82143
{
144+
var settings = YmmRpcSettings.Default;
145+
var isLite = GetIsLiteEdition();
146+
147+
string details;
148+
if (settings.IsShowProject)
149+
{
150+
var projectName = GetCurrentProjectName();
151+
var displayName = projectName ?? "無題";
152+
details = $"{displayName}.ymmp を編集中...";
153+
}
154+
else
155+
{
156+
details = "動画を編集中...";
157+
}
158+
83159
return new RichPresence
84160
{
85-
Details = "動画を編集中...",
86-
State = IsLiteEdition() ? "Working on YMM4 Lite" : "Working on YMM4",
161+
Details = details,
162+
State = isLite ? "Working on YMM4 Lite" : "Working on YMM4",
87163
Assets = new Assets
88164
{
89165
LargeImageKey = "icon",
@@ -95,31 +171,39 @@ private static RichPresence BuildDefaultPresence()
95171

96172
private static RichPresence BuildCustomPresence(YmmRpcSettings settings)
97173
{
174+
var projectName = GetCurrentProjectName();
175+
var displayName = projectName != null ? $"{projectName}.ymmp" : "無題.ymmp";
176+
177+
var details = ReplacePlaceholders(settings.CustomRpcDetails, displayName);
178+
var state = ReplacePlaceholders(settings.CustomRpcState, displayName);
179+
var largeImageText = ReplacePlaceholders(settings.CustomRpcLargeImageText, displayName);
180+
var smallImageText = ReplacePlaceholders(settings.CustomRpcSmallImageText, displayName);
181+
98182
var presence = new RichPresence
99183
{
100-
Details = NullIfEmpty(settings.CustomRpcDetails),
101-
State = NullIfEmpty(settings.CustomRpcState),
184+
Details = NullIfEmpty(details),
185+
State = NullIfEmpty(state),
102186
Assets = new Assets
103187
{
104188
LargeImageKey = string.IsNullOrEmpty(settings.CustomRpcLargeImageKey) ? "icon" : settings.CustomRpcLargeImageKey,
105-
LargeImageText = NullIfEmpty(settings.CustomRpcLargeImageText),
189+
LargeImageText = NullIfEmpty(largeImageText),
106190
SmallImageKey = NullIfEmpty(settings.CustomRpcSmallImageKey),
107-
SmallImageText = NullIfEmpty(settings.CustomRpcSmallImageText)
191+
SmallImageText = NullIfEmpty(smallImageText)
108192
},
109193
Timestamps = new Timestamps { Start = _startTime }
110194
};
111195

112196
if (!settings.CustomRpcEnableButtons) return presence;
113-
197+
114198
var buttons = new List<Button>(2);
115-
116-
if (!string.IsNullOrEmpty(settings.CustomRpcButton1Label) &&
199+
200+
if (!string.IsNullOrEmpty(settings.CustomRpcButton1Label) &&
117201
!string.IsNullOrEmpty(settings.CustomRpcButton1Url))
118202
{
119203
buttons.Add(new Button { Label = settings.CustomRpcButton1Label, Url = settings.CustomRpcButton1Url });
120204
}
121-
122-
if (!string.IsNullOrEmpty(settings.CustomRpcButton2Label) &&
205+
206+
if (!string.IsNullOrEmpty(settings.CustomRpcButton2Label) &&
123207
!string.IsNullOrEmpty(settings.CustomRpcButton2Url))
124208
{
125209
buttons.Add(new Button { Label = settings.CustomRpcButton2Label, Url = settings.CustomRpcButton2Url });
@@ -131,8 +215,42 @@ private static RichPresence BuildCustomPresence(YmmRpcSettings settings)
131215
return presence;
132216
}
133217

218+
private static string? ReplacePlaceholders(string? input, string displayName)
219+
{
220+
return string.IsNullOrEmpty(input) ? input : input.Replace("{project}", displayName);
221+
}
222+
134223
private static string? NullIfEmpty(string? s) => string.IsNullOrEmpty(s) ? null : s;
135224

225+
private static bool GetIsLiteEdition()
226+
{
227+
if (_isLiteEdition.HasValue) return _isLiteEdition.Value;
228+
229+
var exeName = Process.GetCurrentProcess().MainModule?.FileName ?? "";
230+
if (exeName.Contains("Lite", StringComparison.OrdinalIgnoreCase))
231+
{
232+
_isLiteEdition = true;
233+
return true;
234+
}
235+
236+
try
237+
{
238+
var result = Application.Current?.Dispatcher?.Invoke(() =>
239+
{
240+
var title = Application.Current?.MainWindow?.Title ?? "";
241+
return title.Contains("Lite", StringComparison.OrdinalIgnoreCase);
242+
}) ?? false;
243+
244+
_isLiteEdition = result;
245+
return result;
246+
}
247+
catch
248+
{
249+
_isLiteEdition = false;
250+
return false;
251+
}
252+
}
253+
136254
public void Dispose()
137255
{
138256
if (_disposed) return;
@@ -150,14 +268,4 @@ public void Dispose()
150268

151269
GC.SuppressFinalize(this);
152270
}
153-
154-
private static bool IsLiteEdition()
155-
{
156-
var exeName = Process.GetCurrentProcess().MainModule?.FileName ?? "";
157-
if (exeName.Contains("Lite", StringComparison.OrdinalIgnoreCase))
158-
return true;
159-
160-
var title = Application.Current?.MainWindow?.Title ?? "";
161-
return title.Contains("Lite", StringComparison.OrdinalIgnoreCase);
162-
}
163271
}

0 commit comments

Comments
 (0)