Skip to content

Commit 2f2a0c6

Browse files
feat: adding initial gui that allows signing into twitch
1 parent 9a2df88 commit 2f2a0c6

33 files changed

+1229
-67
lines changed

src/TwitchStreamingTools/.editorconfig

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,9 @@ root = true
44
[*]
55
indent_style = space
66

7+
# ReSharper properties
8+
resharper_csharp_wrap_lines = false
9+
710
# Xml files
811
[*.xml]
912
indent_size = 2

src/TwitchStreamingTools/App.axaml

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,23 @@
11
<Application xmlns="https://github.com/avaloniaui"
22
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
3-
x:Class="SiteMonitor.App"
4-
xmlns:siteMonitor="clr-namespace:SiteMonitor"
3+
x:Class="TwitchStreamingTools.App"
4+
xmlns:twitchStreamingTools="clr-namespace:TwitchStreamingTools"
55
RequestedThemeVariant="Dark">
66
<!-- "Default" ThemeVariant follows system theme variant. "Dark" or "Light" are other available options. -->
77

88
<Application.DataTemplates>
9-
<siteMonitor:ViewLocator />
9+
<twitchStreamingTools:ViewLocator />
1010
</Application.DataTemplates>
1111

1212
<Application.Styles>
1313
<FluentTheme />
14+
<StyleInclude Source="/Assets/icons.axaml" />
1415
</Application.Styles>
1516

1617
<TrayIcon.Icons>
1718
<TrayIcons>
1819
<TrayIcon Icon="/Assets/logo.ico"
19-
ToolTipText="Nullinside Site Monitor">
20+
ToolTipText="Twitch Streaming Tools">
2021
<TrayIcon.Menu>
2122
<NativeMenu>
2223
<NativeMenuItem Header="Show" Click="ShowSettings_OnClick" />

src/TwitchStreamingTools/App.axaml.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,10 @@
55
using Avalonia.Controls.ApplicationLifetimes;
66
using Avalonia.Markup.Xaml;
77

8-
using SiteMonitor.ViewModels;
9-
using SiteMonitor.Views;
8+
using TwitchStreamingTools.ViewModels;
9+
using TwitchStreamingTools.Views;
1010

11-
namespace SiteMonitor;
11+
namespace TwitchStreamingTools;
1212

1313
/// <summary>
1414
/// Main entry point of the application.
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
<Styles xmlns="https://github.com/avaloniaui"
2+
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
3+
<Style>
4+
<Style.Resources>
5+
<!-- Assets from: https://avaloniaui.github.io/icons.html -->
6+
<StreamGeometry x:Key="InprivateAccountRegular">M21 16C22.3062 16 23.4175 16.8348 23.8293 18H14V17.5H7C6.2203 17.5 5.57955 18.0949 5.50687 18.8555L5.5 19V19.7146C5.5 22.389 8.88879 24.5 14 24.5V24H21.4712C19.6819 25.2427 17.0617 26 14 26C8.21053 26 4 23.4333 4 19.7146V19C4 17.3431 5.34315 16 7 16H21Z M24 19V19.7146C24 19.9815 23.9766 20.2436 23.9308 20.5H14V19H24Z M23.6286 21.5H14V23H22.6339C23.0614 22.5387 23.397 22.0359 23.6286 21.5Z M19.9536 7.25C19.9842 7.4957 20 7.746 20 8C20 8.254 19.9842 8.5043 19.9536 8.75H14V7.25H19.9536Z M19.7408 6.25C19.5777 5.71438 19.3417 5.21053 19.0444 4.75H14V6.25H19.7408Z M14 2C15.6531 2 17.1501 2.66854 18.2353 3.75H14V3.5C11.5147 3.5 9.5 5.51472 9.5 8C9.5 10.4853 11.5147 12.5 14 12.5V12.25H18.2353C17.1501 13.3315 15.6531 14 14 14C10.6863 14 8 11.3137 8 8C8 4.68629 10.6863 2 14 2Z M19.0444 11.25H14V9.75H19.7408C19.5777 10.2856 19.3417 10.7895 19.0444 11.25Z</StreamGeometry>
7+
<StreamGeometry x:Key="LineHorizontal3Regular">M2 4.5C2 4.22386 2.22386 4 2.5 4H17.5C17.7761 4 18 4.22386 18 4.5C18 4.77614 17.7761 5 17.5 5H2.5C2.22386 5 2 4.77614 2 4.5Z M2 9.5C2 9.22386 2.22386 9 2.5 9H17.5C17.7761 9 18 9.22386 18 9.5C18 9.77614 17.7761 10 17.5 10H2.5C2.22386 10 2 9.77614 2 9.5Z M2.5 14C2.22386 14 2 14.2239 2 14.5C2 14.7761 2.22386 15 2.5 15H17.5C17.7761 15 18 14.7761 18 14.5C18 14.2239 17.7761 14 17.5 14H2.5Z</StreamGeometry>
8+
<StreamGeometry x:Key="ChatRegular">M14.0038862,2.5 C20.3551608,2.5 25.5038862,7.64872538 25.5038862,14 C25.5038862,20.3512746 20.3551608,25.5 14.0038862,25.5 C12.0828262,25.5 10.2289934,25.0277557 8.57453454,24.1400553 L4.06949813,25.4927799 C3.40830889,25.6913248 2.71135661,25.3162775 2.51281166,24.6550883 C2.44236748,24.4204969 2.44239769,24.1703786 2.5128929,23.935823 L3.86597493,19.4333464 C2.97690068,17.777898 2.50388618,15.9226229 2.50388618,14 C2.50388618,7.64872538 7.65261155,2.5 14.0038862,2.5 Z M14.0038862,4 C8.48103868,4 4.00388618,8.4771525 4.00388618,14 C4.00388618,15.7703119 4.46384891,17.4718347 5.32571954,18.9725127 L5.48656853,19.2525809 L4.08316234,23.9225148 L8.75512584,22.5196672 L9.03501121,22.6802549 C10.5348218,23.5407899 12.2350195,24 14.0038862,24 C19.5267337,24 24.0038862,19.5228475 24.0038862,14 C24.0038862,8.4771525 19.5267337,4 14.0038862,4 Z M10.2538862,15.5 L14.7521489,15.5 C15.1663625,15.5 15.5021489,15.8357864 15.5021489,16.25 C15.5021489,16.6296958 15.219995,16.943491 14.8539195,16.9931534 L14.7521489,17 L10.2538862,17 C9.83967261,17 9.50388618,16.6642136 9.50388618,16.25 C9.50388618,15.8703042 9.78604006,15.556509 10.1521156,15.5068466 L10.2538862,15.5 L14.7521489,15.5 L10.2538862,15.5 Z M10.2538862,11 L17.7583662,11 C18.1725798,11 18.5083662,11.3357864 18.5083662,11.75 C18.5083662,12.1296958 18.2262123,12.443491 17.8601368,12.4931534 L17.7583662,12.5 L10.2538862,12.5 C9.83967261,12.5 9.50388618,12.1642136 9.50388618,11.75 C9.50388618,11.3703042 9.78604006,11.056509 10.1521156,11.0068466 L10.2538862,11 L17.7583662,11 L10.2538862,11 Z</StreamGeometry>
9+
</Style.Resources>
10+
</Style>
11+
</Styles>
23.6 KB
Loading
27.5 KB
Loading
Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
using System.Collections.Generic;
2+
3+
using Avalonia.Input.Platform;
4+
5+
namespace TwitchStreamingTools;
6+
7+
/// <summary>
8+
/// Constants used throughout the application.
9+
/// </summary>
10+
public static class Constants {
11+
#if DEBUG
12+
/// <summary>
13+
/// The twitch app client id.
14+
/// </summary>
15+
public static string TWITCH_CLIENT_ID = "cvipqhi9y6ri8yhv0w8ryxokxh0ebd";
16+
17+
/// <summary>
18+
/// The domain that the api service is hosted at.
19+
/// </summary>
20+
public static string API_SITE_DOMAIN = "localhost:5036";
21+
#else
22+
/// <summary>
23+
/// The twitch app client id.
24+
/// </summary>
25+
public static string TWITCH_CLIENT_ID = "gi1eu8xu9tl6vkjqz4tjqkdzfmcq5h";
26+
27+
/// <summary>
28+
/// The domain that the api service is hosted at.
29+
/// </summary>
30+
public static string API_SITE_DOMAIN = "nullinside.com";
31+
#endif
32+
33+
/// <summary>
34+
/// The twitch app redirect link.
35+
/// </summary>
36+
public static string TWITCH_CLIENT_REDIRECT = $"http://{API_SITE_DOMAIN}/api/v1/user/twitch-login/twitch-streaming-tools";
37+
38+
/// <summary>
39+
/// The reference to the clipboard API.
40+
/// </summary>
41+
/// <remarks>This is a hack because it's hard to get to.</remarks>
42+
public static IClipboard? CLIPBOARD;
43+
44+
/// <summary>
45+
/// The twitch permissions to request.
46+
/// </summary>
47+
public static readonly IEnumerable<string> TWITCH_SCOPES = new[] {
48+
"analytics:read:extensions",
49+
"analytics:read:games",
50+
"bits:read",
51+
"channel:edit:commercial",
52+
"channel:manage:broadcast",
53+
"channel:manage:extensions",
54+
"channel:manage:polls",
55+
"channel:manage:predictions",
56+
"channel:manage:redemptions",
57+
"channel:manage:schedule",
58+
"channel:manage:videos",
59+
"channel:read:editors",
60+
"channel:read:goals",
61+
"channel:read:hype_train",
62+
"channel:read:polls",
63+
"channel:read:predictions",
64+
"channel:read:redemptions",
65+
"channel:read:stream_key",
66+
"channel:read:subscriptions",
67+
"clips:edit",
68+
"moderation:read",
69+
"moderator:manage:automod",
70+
"user:edit",
71+
"user:edit:follows",
72+
"user:manage:blocked_users",
73+
"user:read:blocked_users",
74+
"user:read:broadcast",
75+
"user:read:email",
76+
"user:read:follows",
77+
"user:read:subscriptions",
78+
"channel_subscriptions",
79+
"channel_commercial",
80+
"channel_editor",
81+
"user_follows_edit",
82+
"channel_read",
83+
"user_read",
84+
"user_blocks_read",
85+
"user_blocks_edit",
86+
"channel:moderate",
87+
"chat:edit",
88+
"chat:read",
89+
"whispers:read",
90+
"whispers:edit"
91+
};
92+
}

src/TwitchStreamingTools/Models/Configuration.cs

Lines changed: 21 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,19 @@
1-
using System.IO;
2-
using System.Reflection;
1+
using System;
2+
using System.IO;
33

44
using Newtonsoft.Json;
55

6-
namespace SiteMonitor.Models;
6+
using Nullinside.Api.Common.Twitch;
7+
8+
namespace TwitchStreamingTools.Models;
79

810
/// <summary>
911
/// The configuration of the application.
1012
/// </summary>
1113
public class Configuration {
1214
private static readonly string s_configLocation =
13-
Path.Combine(Path.GetDirectoryName(Assembly.GetEntryAssembly()?.Location) ?? string.Empty, "config.json");
15+
Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "nullinside",
16+
"twitch-streaming-tools", "config.json");
1417

1518
private static Configuration? s_instance;
1619

@@ -27,6 +30,16 @@ public static Configuration Instance {
2730
}
2831
}
2932

33+
/// <summary>
34+
/// The twitch OAuth token.
35+
/// </summary>
36+
public OAuthResponse? OAuth { get; set; }
37+
38+
/// <summary>
39+
/// The twitch application configuration for getting OAuth tokens.
40+
/// </summary>
41+
public TwitchAppConfig? TwitchAppConfig { get; set; }
42+
3043
private static Configuration? ReadConfiguration() {
3144
try {
3245
string json = File.ReadAllText(s_configLocation);
@@ -39,9 +52,11 @@ public static Configuration Instance {
3952
/// Writes the configuration file to disk.
4053
/// </summary>
4154
/// <returns>True if successful, false otherwise.</returns>
42-
public static bool WriteConfiguration() {
55+
public bool WriteConfiguration() {
4356
try {
44-
string json = JsonConvert.SerializeObject(Instance);
57+
Directory.CreateDirectory(Path.GetDirectoryName(s_configLocation)!);
58+
59+
string json = JsonConvert.SerializeObject(this);
4560
File.WriteAllText(s_configLocation, json);
4661
return true;
4762
}
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
using System;
2+
3+
using Avalonia;
4+
using Avalonia.Controls;
5+
using Avalonia.Media;
6+
7+
namespace TwitchStreamingTools.Models;
8+
9+
/// <summary>
10+
/// Represents a menu item on the left navigation of the main UI.
11+
/// </summary>
12+
public class MenuItem {
13+
/// <summary>
14+
/// Initializes a new instance of the <see cref="MenuItem" /> class.
15+
/// </summary>
16+
/// <param name="type">The view model to generate the page from.</param>
17+
/// <param name="iconKey">The key name of the icon to use.</param>
18+
public MenuItem(Type type, string iconKey) {
19+
ModelType = type;
20+
Label = type.Name.Replace("ViewModel", "");
21+
22+
Application.Current!.TryFindResource(iconKey, out object? icon);
23+
Icon = (StreamGeometry)icon!;
24+
}
25+
26+
/// <summary>
27+
/// The display name on the screen.
28+
/// </summary>
29+
public string Label { get; set; }
30+
31+
/// <summary>
32+
/// The view model.
33+
/// </summary>
34+
public Type ModelType { get; set; }
35+
36+
/// <summary>
37+
/// The view model.
38+
/// </summary>
39+
public StreamGeometry Icon { get; set; }
40+
}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
using System;
2+
3+
using Newtonsoft.Json;
4+
5+
/// <summary>
6+
/// A JSON representation of an OAuth token.
7+
/// </summary>
8+
public class OAuthResponse {
9+
/// <summary>
10+
/// The OAuth token.
11+
/// </summary>
12+
[JsonProperty("bearer")]
13+
public string Bearer { get; set; } = null!;
14+
15+
/// <summary>
16+
/// The refresh token.
17+
/// </summary>
18+
[JsonProperty("refresh")]
19+
public string Refresh { get; set; } = null!;
20+
21+
/// <summary>
22+
/// The UTC time to refresh the token.
23+
/// </summary>
24+
[JsonProperty("expiresUtc")]
25+
public DateTime ExpiresUtc { get; set; }
26+
}

0 commit comments

Comments
 (0)