pushing stuff
This commit is contained in:
parent
cb4f70de6e
commit
8a38300cf1
@ -3,6 +3,8 @@ using Microsoft.UI.Xaml.Controls;
|
||||
using System;
|
||||
using System.IO;
|
||||
using WinUIEx;
|
||||
using Microsoft.Windows.AppNotifications;
|
||||
|
||||
|
||||
// To learn more about WinUI, the WinUI project structure,
|
||||
// and more about our project templates, see: http://aka.ms/winui-project-info.
|
||||
@ -12,7 +14,7 @@ namespace wakka
|
||||
public partial class App : Application
|
||||
{
|
||||
public Window m_window;
|
||||
|
||||
|
||||
public readonly static Windows.Storage.ApplicationDataContainer LocalSettingsData =
|
||||
Windows.Storage.ApplicationData.Current.LocalSettings;
|
||||
|
||||
|
84
Bink.cs
84
Bink.cs
@ -1,4 +1,7 @@
|
||||
using System.Collections.Generic;
|
||||
using Microsoft.UI.Xaml;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
@ -7,36 +10,89 @@ namespace wakka
|
||||
public class BinkPost
|
||||
{
|
||||
[JsonPropertyName("user")]
|
||||
public string? User { get; set; }
|
||||
public required string User { get; set; }
|
||||
[JsonPropertyName("body")]
|
||||
public string? Body { get; set; }
|
||||
public required string Body { get; set; }
|
||||
[JsonPropertyName("time")]
|
||||
public long Time { get; set; }
|
||||
public required long Time { get; set; }
|
||||
public string TimeString { get; set; } = string.Empty;
|
||||
}
|
||||
|
||||
public class Bink
|
||||
public static class Bink
|
||||
{
|
||||
private static SshConnection Ssh { get; set; } = new SshConnection();
|
||||
private static DispatcherTimer? timer = null;
|
||||
public static readonly ObservableCollection<BinkPost> LoadedBinks = [];
|
||||
private static List<BinkPost>? BinkData = null;
|
||||
|
||||
public void PostBink(string message)
|
||||
public static void Initialize()
|
||||
{
|
||||
Ssh.RunCommandWithInput("town bink --pipe", message);
|
||||
if (timer == null)
|
||||
StartTimer();
|
||||
if (BinkData == null)
|
||||
{
|
||||
BinkData = AllBinks();
|
||||
if (BinkData != null)
|
||||
{
|
||||
foreach (var bink in BinkData)
|
||||
{
|
||||
SetBinkDateString(bink);
|
||||
LoadedBinks.Add(bink);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public List<BinkPost>? AllBinks()
|
||||
public static void PostBink(string message)
|
||||
{
|
||||
return JsonSerializer.Deserialize<List<BinkPost>>(Ssh.RunCommand("town bink --dump"));
|
||||
SshConnection.RunCommandWithInput("town bink --pipe", message);
|
||||
}
|
||||
|
||||
public List<BinkPost>? BinksBefore(long TimeStamp)
|
||||
public static List<BinkPost>? AllBinks()
|
||||
{
|
||||
return JsonSerializer.Deserialize<List<BinkPost>>(Ssh.RunCommand($"town bink --dump-before {TimeStamp}"));
|
||||
return JsonSerializer.Deserialize<List<BinkPost>>(SshConnection.RunCommand("town bink --dump"));
|
||||
}
|
||||
|
||||
public List<BinkPost>? BinksAfter(long TimeStamp)
|
||||
public static List<BinkPost>? BinksBefore(long TimeStamp)
|
||||
{
|
||||
return JsonSerializer.Deserialize<List<BinkPost>>(Ssh.RunCommand($"town bink --dump-after {TimeStamp}"));
|
||||
return JsonSerializer.Deserialize<List<BinkPost>>(SshConnection.RunCommand($"town bink --dump-before {TimeStamp}"));
|
||||
}
|
||||
|
||||
public static List<BinkPost>? BinksAfter(long TimeStamp)
|
||||
{
|
||||
return JsonSerializer.Deserialize<List<BinkPost>>(SshConnection.RunCommand($"town bink --dump-after {TimeStamp}"));
|
||||
}
|
||||
|
||||
public static void SetBinkDateString(BinkPost bink)
|
||||
{
|
||||
var date = DateTimeOffset.FromUnixTimeSeconds(bink.Time / 1000000000).DateTime.ToLocalTime();
|
||||
bink.TimeString = date.ToString("HH:mm (dddd, MMMM dd, yyyy)");
|
||||
}
|
||||
|
||||
public static void GetNewBinks()
|
||||
{
|
||||
var BinkList = BinksAfter(LoadedBinks[0].Time);
|
||||
if (BinkList != null)
|
||||
{
|
||||
BinkList.Reverse();
|
||||
foreach (var bink in BinkList)
|
||||
{
|
||||
SetBinkDateString(bink);
|
||||
LoadedBinks.Insert(0, bink);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void StartTimer()
|
||||
{
|
||||
timer = new DispatcherTimer();
|
||||
timer.Interval = TimeSpan.FromSeconds(20);
|
||||
timer.Tick += Timer_Tick;
|
||||
timer.Start();
|
||||
}
|
||||
|
||||
private static void Timer_Tick(object? sender, object? e)
|
||||
{
|
||||
GetNewBinks();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -15,8 +15,8 @@
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<CommandBar DefaultLabelPosition="Right" Grid.Row="0">
|
||||
<AppBarButton Icon="Refresh" Label="Update" Click="GetNewBinksButton" />
|
||||
<AppBarButton Icon="Add" Label="Post" Click="OnBinkCreate" />
|
||||
<AppBarButton Icon="Refresh" Label="Update" Click="RefreshButton" />
|
||||
<AppBarButton Icon="Add" Label="Post" Click="OnBinkCreateButton" />
|
||||
</CommandBar>
|
||||
|
||||
<ContentDialog
|
||||
|
@ -1,12 +1,6 @@
|
||||
using Microsoft.UI.Xaml.Controls;
|
||||
using Microsoft.UI.Xaml.Navigation;
|
||||
using Org.BouncyCastle.Tls;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Threading.Tasks;
|
||||
using System.Threading;
|
||||
using Microsoft.UI.Xaml;
|
||||
using Microsoft.UI.Xaml.Controls;
|
||||
using System;
|
||||
|
||||
// To learn more about WinUI, the WinUI project structure,
|
||||
// and more about our project templates, see: http://aka.ms/winui-project-info.
|
||||
@ -18,44 +12,12 @@ namespace wakka
|
||||
/// </summary>
|
||||
public sealed partial class BinkPage : Page
|
||||
{
|
||||
private DispatcherTimer timer;
|
||||
|
||||
private readonly ObservableCollection<BinkPost> Binks = [];
|
||||
private static Bink Bink { get; set; } = new Bink();
|
||||
|
||||
public BinkPage()
|
||||
{
|
||||
this.InitializeComponent();
|
||||
StartTimer();
|
||||
var BinkList = Bink.AllBinks();
|
||||
if (BinkList != null)
|
||||
{
|
||||
foreach (var bink in BinkList)
|
||||
{
|
||||
SetBinkDateString(bink);
|
||||
Binks.Add(bink);
|
||||
}
|
||||
}
|
||||
binksListView.ItemsSource = Binks;
|
||||
}
|
||||
public void SetBinkDateString (BinkPost bink)
|
||||
{
|
||||
var date = DateTimeOffset.FromUnixTimeSeconds(bink.Time / 1000000000).DateTime.ToLocalTime();
|
||||
bink.TimeString = date.ToString("HH:mm (dddd, MMMM dd, yyyy)");
|
||||
}
|
||||
public void GetNewBinks()
|
||||
{
|
||||
var BinkList = Bink.BinksAfter(Binks[0].Time);
|
||||
if (BinkList != null)
|
||||
{
|
||||
BinkList.Reverse();
|
||||
foreach (var bink in BinkList)
|
||||
{
|
||||
SetBinkDateString(bink);
|
||||
Binks.Insert(0, bink);
|
||||
}
|
||||
}
|
||||
binksListView.ItemsSource = Bink.LoadedBinks;
|
||||
}
|
||||
|
||||
private void BinkSubmit(ContentDialog sender, ContentDialogButtonClickEventArgs args)
|
||||
{
|
||||
var message = binkComposeBox.Text;
|
||||
@ -63,10 +25,10 @@ namespace wakka
|
||||
{
|
||||
Bink.PostBink(message);
|
||||
binkComposeBox.Text = string.Empty;
|
||||
GetNewBinks();
|
||||
Bink.GetNewBinks();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void OnTextChanged(object sender, TextChangedEventArgs e)
|
||||
{
|
||||
if (string.IsNullOrEmpty(binkComposeBox.Text))
|
||||
@ -79,27 +41,16 @@ namespace wakka
|
||||
}
|
||||
}
|
||||
|
||||
private async void OnBinkCreate(object sender, RoutedEventArgs e)
|
||||
private async void OnBinkCreateButton(object sender, RoutedEventArgs e)
|
||||
{
|
||||
binkComposeDialog.IsPrimaryButtonEnabled = false;
|
||||
await binkComposeDialog.ShowAsync();
|
||||
}
|
||||
public void GetNewBinksButton(object sender, Microsoft.UI.Xaml.RoutedEventArgs e)
|
||||
public void RefreshButton(object sender, RoutedEventArgs e)
|
||||
{
|
||||
GetNewBinks();
|
||||
Bink.GetNewBinks();
|
||||
}
|
||||
|
||||
private void StartTimer()
|
||||
{
|
||||
timer = new DispatcherTimer();
|
||||
timer.Interval = TimeSpan.FromSeconds(20);
|
||||
timer.Tick += Timer_Tick;
|
||||
timer.Start();
|
||||
}
|
||||
|
||||
private void Timer_Tick(object? sender, object? e)
|
||||
{
|
||||
GetNewBinks();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
139
Feels.cs
139
Feels.cs
@ -1,44 +1,157 @@
|
||||
using System.Collections.Generic;
|
||||
using Microsoft.UI.Xaml;
|
||||
using Renci.SshNet;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.ComponentModel;
|
||||
using System.Linq;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Serialization;
|
||||
using Windows.ApplicationModel.VoiceCommands;
|
||||
using Windows.Storage.Search;
|
||||
|
||||
namespace wakka
|
||||
{
|
||||
public class FeelsPost
|
||||
{
|
||||
[JsonPropertyName("user")]
|
||||
public string? User { get; set; }
|
||||
public required string User { get; set; }
|
||||
[JsonPropertyName("path")]
|
||||
public string? Path { get; set; }
|
||||
public required string Path { get; set; }
|
||||
[JsonPropertyName("m_time")]
|
||||
public long M_Time { get; set; }
|
||||
public required long M_Time { get; set; }
|
||||
[JsonPropertyName("reported_date")]
|
||||
public required long ReportedDate { get; set; }
|
||||
public string TimeString { get; set; } = string.Empty;
|
||||
public string Body { get; set; } = string.Empty;
|
||||
|
||||
public int WordCount { get; set; } = 0;
|
||||
}
|
||||
|
||||
internal class Feels
|
||||
public static class Feels
|
||||
{
|
||||
private static SshConnection Ssh { get; set; } = new SshConnection();
|
||||
public static readonly ObservableCollection<FeelsPost> LoadedFeelsPosts = [];
|
||||
private static DispatcherTimer? Timer = null;
|
||||
private static List<List<FeelsPost>>? LoadTimeMetadata = null;
|
||||
private static int CurrentChunk = 0;
|
||||
|
||||
public List<FeelsPost>? AllFeels()
|
||||
public static void Initialize()
|
||||
{
|
||||
return JsonSerializer.Deserialize<List<FeelsPost>>(Ssh.RunCommand("~nebula/bin/dumpfeels"));
|
||||
if (Timer == null)
|
||||
StartTimer();
|
||||
if (LoadTimeMetadata == null)
|
||||
{
|
||||
var feels = AllFeels();
|
||||
if (feels != null)
|
||||
{
|
||||
LoadTimeMetadata = (List<List<FeelsPost>>)feels.Chunk(10).Select(chunk => chunk.ToList()).ToList();
|
||||
LoadFeelsChunk();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public List<FeelsPost>? FeelsAfter(long TimeStamp)
|
||||
public static void LoadFeelsChunk()
|
||||
{
|
||||
return JsonSerializer.Deserialize<List<FeelsPost>>(Ssh.RunCommand($"~nebula/bin/dumpfeels --after {TimeStamp}"));
|
||||
if (LoadTimeMetadata == null)
|
||||
return;
|
||||
var chunk = LoadTimeMetadata[CurrentChunk];
|
||||
foreach (var feel in chunk)
|
||||
{
|
||||
ConstructFeel(feel);
|
||||
LoadedFeelsPosts.Add(feel);
|
||||
}
|
||||
CurrentChunk++;
|
||||
}
|
||||
|
||||
public List<FeelsPost>? FeelsFromUser(string User, List<FeelsPost> Feels)
|
||||
private static void StartTimer()
|
||||
{
|
||||
Timer = new DispatcherTimer();
|
||||
Timer.Interval = TimeSpan.FromSeconds(20);
|
||||
Timer.Tick += Timer_Tick;
|
||||
Timer.Start();
|
||||
}
|
||||
|
||||
private static void Timer_Tick(object? sender, object? e)
|
||||
{
|
||||
GetNewFeels();
|
||||
}
|
||||
|
||||
public static void GetNewFeels()
|
||||
{
|
||||
var newFeels = FeelsAfter(LoadedFeelsPosts[0].M_Time);
|
||||
if (newFeels != null)
|
||||
{
|
||||
var additions = new List<FeelsPost>();
|
||||
foreach (var newFeel in newFeels)
|
||||
{
|
||||
ConstructFeel(newFeel);
|
||||
FeelsPost? toRemove = null;
|
||||
foreach (var liveFeel in LoadedFeelsPosts)
|
||||
{
|
||||
if (liveFeel.Path.Equals(newFeel.Path))
|
||||
{
|
||||
toRemove = liveFeel;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (toRemove != null)
|
||||
LoadedFeelsPosts.Remove(toRemove);
|
||||
additions.Add(newFeel);
|
||||
}
|
||||
additions.Reverse();
|
||||
foreach (var feel in additions)
|
||||
{
|
||||
LoadedFeelsPosts.Insert(0, feel);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static string GetTodayFeelPath()
|
||||
{
|
||||
var dateString = DateTime.Now.ToString("yyyyMMdd");
|
||||
return $"/home/{SshConnection.User}/.ttbp/entries/{dateString}.txt";
|
||||
}
|
||||
|
||||
public static string GetTodayFeelBody()
|
||||
{
|
||||
|
||||
return SshConnection.RunCommand($"cat {GetTodayFeelPath()}");
|
||||
}
|
||||
|
||||
public static void PostFeel(string body)
|
||||
{
|
||||
SshConnection.RunCommandWithInput($"cat > {GetTodayFeelPath()}", body);
|
||||
}
|
||||
|
||||
public static List<FeelsPost>? AllFeels()
|
||||
{
|
||||
return JsonSerializer.Deserialize<List<FeelsPost>>(SshConnection.RunCommand("~nebula/bin/dumpfeels"));
|
||||
}
|
||||
|
||||
public static List<FeelsPost>? FeelsAfter(long TimeStamp)
|
||||
{
|
||||
return JsonSerializer.Deserialize<List<FeelsPost>>(SshConnection.RunCommand($"~nebula/bin/dumpfeels --after {TimeStamp}"));
|
||||
}
|
||||
|
||||
public static List<FeelsPost>? FeelsFromUser(string User, List<FeelsPost> Feels)
|
||||
{
|
||||
return Feels.FindAll(i => i.User == User);
|
||||
}
|
||||
|
||||
public string GetFeelsBody(FeelsPost Post)
|
||||
public static string GetFeelsBody(FeelsPost Post)
|
||||
{
|
||||
return Ssh.RunCommand($"cat {Post.Path}");
|
||||
return SshConnection.RunCommand($"cat {Post.Path}");
|
||||
}
|
||||
|
||||
private static void ConstructFeel(FeelsPost feel)
|
||||
{
|
||||
var date = DateTimeOffset.FromUnixTimeSeconds(feel.M_Time).DateTime.ToLocalTime();
|
||||
feel.TimeString = date.ToString("HH:mm (dddd, MMMM dd, yyyy)");
|
||||
var body = GetFeelsBody(feel);
|
||||
char[] delimiters = new char[] { ' ', '\n' };
|
||||
feel.WordCount = body.Split(delimiters, StringSplitOptions.RemoveEmptyEntries).Length;
|
||||
feel.Body = body;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -11,10 +11,10 @@
|
||||
|
||||
<Grid>
|
||||
<ScrollViewer x:Name="scrollViewer" ViewChanged="ViewChanged">
|
||||
<ListView Grid.Row="0" x:Name="feelsListView" SelectionMode="None">
|
||||
<ListView x:Name="feelsListView" SelectionMode="None">
|
||||
<ListView.ItemTemplate>
|
||||
<DataTemplate x:DataType="local:FeelsPost">
|
||||
<Expander Width="600" Margin="0,10,0,10" IsExpanded="True" CornerRadius="8">
|
||||
<Expander HorizontalAlignment="Left" MaxWidth="1200" Margin="0,10,0,10" IsExpanded="True" CornerRadius="8">
|
||||
<Expander.Header>
|
||||
<StackPanel Margin="10,10,10,10" HorizontalAlignment="Left">
|
||||
<StackPanel Padding="0,0,0,5" Orientation="Horizontal">
|
||||
|
@ -1,8 +1,10 @@
|
||||
using Microsoft.UI.Xaml;
|
||||
using Microsoft.UI.Xaml.Controls;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Linq;
|
||||
using Microsoft.Windows.AppNotifications;
|
||||
|
||||
// To learn more about WinUI, the WinUI project structure,
|
||||
// and more about our project templates, see: http://aka.ms/winui-project-info.
|
||||
@ -14,34 +16,10 @@ namespace wakka
|
||||
/// </summary>
|
||||
public sealed partial class FeelsFeedPage : Page
|
||||
{
|
||||
private readonly Feels Feels = new Feels();
|
||||
private readonly ObservableCollection<FeelsPost> LiveFeelsPosts = [];
|
||||
private readonly List<List<FeelsPost>> AllFeels;
|
||||
private int CurrentChunk = 0;
|
||||
|
||||
public FeelsFeedPage()
|
||||
{
|
||||
this.InitializeComponent();
|
||||
var feels = Feels.AllFeels();
|
||||
AllFeels = (List<List<FeelsPost>>)feels.Chunk(4).Select(chunk => chunk.ToList()).ToList();
|
||||
LoadFeelsChunk();
|
||||
feelsListView.ItemsSource = LiveFeelsPosts;
|
||||
}
|
||||
|
||||
private void LoadFeelsChunk()
|
||||
{
|
||||
var chunk = AllFeels[CurrentChunk];
|
||||
foreach (var feel in chunk)
|
||||
{
|
||||
var date = DateTimeOffset.FromUnixTimeSeconds(feel.M_Time).DateTime.ToLocalTime();
|
||||
feel.TimeString = date.ToString("HH:mm (dddd, MMMM dd, yyyy)");
|
||||
var body = Feels.GetFeelsBody(feel);
|
||||
char[] delimiters = new char[] { ' ', '\n' };
|
||||
feel.WordCount = body.Split(delimiters, StringSplitOptions.RemoveEmptyEntries).Length;
|
||||
feel.Body = body;
|
||||
LiveFeelsPosts.Add(feel);
|
||||
}
|
||||
CurrentChunk++;
|
||||
feelsListView.ItemsSource = Feels.LoadedFeelsPosts;
|
||||
}
|
||||
|
||||
private void ViewChanged(object sender, ScrollViewerViewChangedEventArgs e)
|
||||
@ -51,7 +29,7 @@ namespace wakka
|
||||
{
|
||||
if (scrollViewer.VerticalOffset >= scrollViewer.ScrollableHeight)
|
||||
{
|
||||
LoadFeelsChunk();
|
||||
Feels.LoadFeelsChunk();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -14,11 +14,34 @@
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="*" />
|
||||
</Grid.RowDefinitions>
|
||||
<SelectorBar Grid.Row="0" x:Name="feelsSelectorBar" SelectionChanged="SelectorChanged">
|
||||
<SelectorBarItem x:Name="feedSelectorBarItem" Text="Feed" IsSelected="True" />
|
||||
<!--<SelectorBarItem x:Name="usersSelectorBarItem" Text="Users" />-->
|
||||
</SelectorBar>
|
||||
|
||||
<Grid Grid.Row="0">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="Auto"/>
|
||||
<ColumnDefinition Width="*"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
<SelectorBar Grid.Column="0" x:Name="feelsSelectorBar" SelectionChanged="SelectorChanged">
|
||||
<SelectorBarItem x:Name="feedSelectorBarItem" Text="Feed" IsSelected="True" />
|
||||
<!--<SelectorBarItem x:Name="usersSelectorBarItem" Text="Users" />-->
|
||||
</SelectorBar>
|
||||
<CommandBar Grid.Column="1" DefaultLabelPosition="Right" HorizontalAlignment="Right" x:Name="feelsCommandBar">
|
||||
<AppBarButton Icon="Add" Label="New Feel" Click="OnFeelsCreateButton"/>
|
||||
</CommandBar>
|
||||
</Grid>
|
||||
<Frame Grid.Row="1" x:Name="FeelsNavigationFrame" IsNavigationStackEnabled="False" />
|
||||
<ContentDialog
|
||||
x:Name="feelsComposeDialog"
|
||||
Title="New Feels"
|
||||
PrimaryButtonText="Post"
|
||||
CloseButtonText="Cancel"
|
||||
PrimaryButtonClick="OnFeelsSubmitButton">
|
||||
<TextBox
|
||||
PlaceholderText="Your feels here..."
|
||||
Width="700"
|
||||
Height="300"
|
||||
TextWrapping="Wrap"
|
||||
AcceptsReturn="True"
|
||||
TextChanged="OnTextChanged"
|
||||
x:Name="feelsComposeBox"/>
|
||||
</ContentDialog>
|
||||
</Grid>
|
||||
</Page>
|
||||
|
@ -1,18 +1,5 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Runtime.InteropServices.WindowsRuntime;
|
||||
using Windows.Foundation;
|
||||
using Windows.Foundation.Collections;
|
||||
using Microsoft.UI.Xaml;
|
||||
using Microsoft.UI.Xaml.Controls;
|
||||
using Microsoft.UI.Xaml.Controls.Primitives;
|
||||
using Microsoft.UI.Xaml.Data;
|
||||
using Microsoft.UI.Xaml.Input;
|
||||
using Microsoft.UI.Xaml.Media;
|
||||
using Microsoft.UI.Xaml.Navigation;
|
||||
using Microsoft.UI.Xaml.Media.Animation;
|
||||
using System;
|
||||
|
||||
// To learn more about WinUI, the WinUI project structure,
|
||||
// and more about our project templates, see: http://aka.ms/winui-project-info.
|
||||
@ -33,5 +20,44 @@ namespace wakka
|
||||
{
|
||||
FeelsNavigationFrame.Navigate(typeof(FeelsFeedPage));
|
||||
}
|
||||
|
||||
private async void OnFeelsCreateButton(object sender, Microsoft.UI.Xaml.RoutedEventArgs e)
|
||||
{
|
||||
var path = Feels.GetTodayFeelPath();
|
||||
if (SshConnection.DoesFileExist(path))
|
||||
{
|
||||
feelsComposeBox.Text = SshConnection.RunCommand($"cat {path}");
|
||||
feelsComposeDialog.IsPrimaryButtonEnabled = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
feelsComposeBox.Text = string.Empty;
|
||||
feelsComposeDialog.IsPrimaryButtonEnabled = false;
|
||||
}
|
||||
await feelsComposeDialog.ShowAsync();
|
||||
}
|
||||
|
||||
private void OnFeelsSubmitButton(ContentDialog sender, ContentDialogButtonClickEventArgs args)
|
||||
{
|
||||
var message = feelsComposeBox.Text;
|
||||
if (!string.IsNullOrEmpty(message))
|
||||
{
|
||||
Feels.PostFeel(message);
|
||||
feelsComposeBox.Text = string.Empty;
|
||||
Feels.GetNewFeels();
|
||||
}
|
||||
}
|
||||
|
||||
private void OnTextChanged(object sender, TextChangedEventArgs e)
|
||||
{
|
||||
if (string.IsNullOrEmpty(feelsComposeBox.Text))
|
||||
{
|
||||
feelsComposeDialog.IsPrimaryButtonEnabled = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
feelsComposeDialog.IsPrimaryButtonEnabled = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -13,18 +13,19 @@ namespace wakka
|
||||
|
||||
public sealed partial class MainWindow : Window
|
||||
{
|
||||
private static SshConnection Ssh { get; set; } = new SshConnection();
|
||||
public Frame RootFrame;
|
||||
public MainWindow()
|
||||
{
|
||||
this.InitializeComponent();
|
||||
RootFrame = rootFrame;
|
||||
Ssh.DeleteSshKey();
|
||||
if (Ssh.KeyExists() & (string)App.LocalSettingsData.Values["username"] != null)
|
||||
//Ssh.DeleteSshKey();
|
||||
if (SshConnection.KeyExists() & (string)App.LocalSettingsData.Values["username"] != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
Ssh.InitializeConnection((string)App.LocalSettingsData.Values["username"]);
|
||||
SshConnection.InitializeConnection((string)App.LocalSettingsData.Values["username"]);
|
||||
Bink.Initialize();
|
||||
Feels.Initialize();
|
||||
RootFrame.Content = new NavigationPage();
|
||||
}
|
||||
catch (Renci.SshNet.Common.SshAuthenticationException)
|
||||
|
@ -34,10 +34,12 @@ namespace wakka
|
||||
{
|
||||
if (selectedItem == binkPageNav)
|
||||
{
|
||||
Bink.GetNewBinks();
|
||||
navigationFrame.Navigate(typeof(BinkPage));
|
||||
}
|
||||
else if (selectedItem == feelsPageNav)
|
||||
{
|
||||
Feels.GetNewFeels();
|
||||
navigationFrame.Navigate(typeof(FeelsNavigationPage));
|
||||
}
|
||||
}
|
||||
|
@ -5,12 +5,14 @@
|
||||
xmlns:mp="http://schemas.microsoft.com/appx/2014/phone/manifest"
|
||||
xmlns:uap="http://schemas.microsoft.com/appx/manifest/uap/windows10"
|
||||
xmlns:rescap="http://schemas.microsoft.com/appx/manifest/foundation/windows10/restrictedcapabilities"
|
||||
xmlns:com="http://schemas.microsoft.com/appx/manifest/com/windows10"
|
||||
xmlns:desktop="http://schemas.microsoft.com/appx/manifest/desktop/windows10"
|
||||
IgnorableNamespaces="uap rescap">
|
||||
|
||||
<Identity
|
||||
Name="8edc9fec-3276-4986-bbf6-5074643d2fdc"
|
||||
Publisher="CN=helix"
|
||||
Version="1.0.0.0" />
|
||||
Publisher="CN=helixnebula"
|
||||
Version="0.0.1.0" />
|
||||
|
||||
<mp:PhoneIdentity PhoneProductId="8edc9fec-3276-4986-bbf6-5074643d2fdc" PhonePublisherId="00000000-0000-0000-0000-000000000000"/>
|
||||
|
||||
@ -42,6 +44,23 @@
|
||||
<uap:DefaultTile Wide310x150Logo="Assets\Wide310x150Logo.png" Square71x71Logo="Assets\SmallTile.png" Square310x310Logo="Assets\LargeTile.png"/>
|
||||
<uap:SplashScreen Image="Assets\SplashScreen.png" />
|
||||
</uap:VisualElements>
|
||||
<Extensions>
|
||||
|
||||
<!--Specify which CLSID to activate when notification is clicked-->
|
||||
<desktop:Extension Category="windows.toastNotificationActivation">
|
||||
<desktop:ToastNotificationActivation ToastActivatorCLSID="9DF6E26B-F9A8-40B3-AD41-AF83E4A07921" />
|
||||
</desktop:Extension>
|
||||
|
||||
<!--Register COM CLSID-->
|
||||
<com:Extension Category="windows.comServer">
|
||||
<com:ComServer>
|
||||
<com:ExeServer Executable="SampleApp\SampleApp.exe" DisplayName="SampleApp" Arguments="----AppNotificationActivated:">
|
||||
<com:Class Id="9DF6E26B-F9A8-40B3-AD41-AF83E4A07921" />
|
||||
</com:ExeServer>
|
||||
</com:ComServer>
|
||||
</com:Extension>
|
||||
|
||||
</Extensions>
|
||||
</Application>
|
||||
</Applications>
|
||||
|
||||
|
@ -1,19 +1,14 @@
|
||||
using Org.BouncyCastle.Crypto;
|
||||
using Org.BouncyCastle.Crypto.Generators;
|
||||
using Org.BouncyCastle.OpenSsl;
|
||||
using Org.BouncyCastle.Security;
|
||||
using Renci.SshNet;
|
||||
using Renci.SshNet;
|
||||
using Renci.SshNet.Common;
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Windows.Media.Protection.PlayReady;
|
||||
|
||||
namespace wakka
|
||||
{
|
||||
public class SshConnection
|
||||
public static class SshConnection
|
||||
{
|
||||
public static string User { get; set; } = string.Empty;
|
||||
|
||||
@ -25,9 +20,9 @@ namespace wakka
|
||||
|
||||
public static string? PublicKey { get; set; } = null;
|
||||
|
||||
public bool KeyExists() => File.Exists(SshKeyPath);
|
||||
public static bool KeyExists() => File.Exists(SshKeyPath);
|
||||
|
||||
public void InitializeConnection(string user)
|
||||
public static void InitializeConnection(string user)
|
||||
{
|
||||
if (!File.Exists(SshKeyPath) || user == string.Empty)
|
||||
{
|
||||
@ -50,7 +45,7 @@ namespace wakka
|
||||
}
|
||||
}
|
||||
|
||||
public string RunCommand(string command)
|
||||
public static string RunCommand(string command)
|
||||
{
|
||||
if (Client == null || !Client.IsConnected)
|
||||
{
|
||||
@ -60,7 +55,18 @@ namespace wakka
|
||||
return rc.Result;
|
||||
}
|
||||
|
||||
public async void RunCommandWithInput(string command, string input)
|
||||
public static bool DoesFileExist(string path)
|
||||
{
|
||||
if (Client == null || !Client.IsConnected)
|
||||
{
|
||||
throw new InvalidOperationException("SSH client is not connected.");
|
||||
}
|
||||
var command = Client.CreateCommand($"test -e {path} && echo 1 || echo 0");
|
||||
var result = command.Execute();
|
||||
return result.Trim() == "1";
|
||||
}
|
||||
|
||||
public static async void RunCommandWithInput(string command, string input)
|
||||
{
|
||||
if (Client == null || !Client.IsConnected)
|
||||
{
|
||||
@ -79,7 +85,7 @@ namespace wakka
|
||||
}
|
||||
}
|
||||
|
||||
public string CreateSshKey()
|
||||
public static string CreateSshKey()
|
||||
{
|
||||
var keygen = new SshKeyGenerator.SshKeyGenerator(2048);
|
||||
var privateKey = keygen.ToPrivateKey();
|
||||
@ -87,7 +93,7 @@ namespace wakka
|
||||
return keygen.ToRfcPublicKey("wakka");
|
||||
}
|
||||
|
||||
public void DeleteSshKey()
|
||||
public static void DeleteSshKey()
|
||||
{
|
||||
if (File.Exists(SshKeyPath))
|
||||
{
|
||||
|
@ -2,12 +2,10 @@ using Microsoft.UI.Xaml;
|
||||
using Microsoft.UI.Xaml.Controls;
|
||||
using Renci.SshNet.Common;
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
using Windows.ApplicationModel.DataTransfer;
|
||||
using Windows.Storage;
|
||||
using Windows.Storage.Pickers;
|
||||
using WinRT.Interop;
|
||||
using static System.Net.Mime.MediaTypeNames;
|
||||
// To learn more about WinUI, the WinUI project structure,
|
||||
// and more about our project templates, see: http://aka.ms/winui-project-info.
|
||||
|
||||
@ -19,8 +17,6 @@ namespace wakka
|
||||
|
||||
public sealed partial class StartupSshPage : Page
|
||||
{
|
||||
private static SshConnection Ssh { get; set; } = new SshConnection();
|
||||
|
||||
public StartupSshPage()
|
||||
{
|
||||
this.InitializeComponent();
|
||||
@ -58,7 +54,7 @@ namespace wakka
|
||||
|
||||
private void CreateSshKey(object sender, RoutedEventArgs e)
|
||||
{
|
||||
var publicKey = Ssh.CreateSshKey();
|
||||
var publicKey = SshConnection.CreateSshKey();
|
||||
if (publicKey != null)
|
||||
{
|
||||
var dataPackage = new DataPackage();
|
||||
@ -66,7 +62,6 @@ namespace wakka
|
||||
Clipboard.SetContent(dataPackage);
|
||||
sshKeyCreateButton.Content = "Public key copied!";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void OnTextChanged(object sender, TextChangedEventArgs e)
|
||||
@ -98,7 +93,9 @@ namespace wakka
|
||||
{
|
||||
try
|
||||
{
|
||||
Ssh.InitializeConnection((string)App.LocalSettingsData.Values["username"]);
|
||||
SshConnection.InitializeConnection((string)App.LocalSettingsData.Values["username"]);
|
||||
Bink.Initialize();
|
||||
Feels.Initialize();
|
||||
var mainWindow = (App.Current as App)?.m_window;
|
||||
if (mainWindow != null)
|
||||
{
|
||||
|
13
wakka.csproj
13
wakka.csproj
@ -1,4 +1,4 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup>
|
||||
<OutputType>WinExe</OutputType>
|
||||
<TargetFramework>net8.0-windows10.0.19041.0</TargetFramework>
|
||||
@ -94,5 +94,16 @@
|
||||
<PublishReadyToRun Condition="'$(Configuration)' != 'Debug'">True</PublishReadyToRun>
|
||||
<PublishTrimmed Condition="'$(Configuration)' == 'Debug'">False</PublishTrimmed>
|
||||
<PublishTrimmed Condition="'$(Configuration)' != 'Debug'">True</PublishTrimmed>
|
||||
<GenerateAppInstallerFile>False</GenerateAppInstallerFile>
|
||||
<AppxPackageSigningEnabled>True</AppxPackageSigningEnabled>
|
||||
<PackageCertificateThumbprint>158AC0CEA4875FEA7A385A58844BE2EA095E5FCE</PackageCertificateThumbprint>
|
||||
<AppxPackageSigningTimestampDigestAlgorithm>SHA256</AppxPackageSigningTimestampDigestAlgorithm>
|
||||
<AppxAutoIncrementPackageRevision>False</AppxAutoIncrementPackageRevision>
|
||||
<AppxSymbolPackageEnabled>False</AppxSymbolPackageEnabled>
|
||||
<GenerateTestArtifacts>True</GenerateTestArtifacts>
|
||||
<AppxBundle>Always</AppxBundle>
|
||||
<AppxBundlePlatforms>x86|x64|arm64</AppxBundlePlatforms>
|
||||
<HoursBetweenUpdateChecks>0</HoursBetweenUpdateChecks>
|
||||
<LangVersion>12.0</LangVersion>
|
||||
</PropertyGroup>
|
||||
</Project>
|
Loading…
x
Reference in New Issue
Block a user