├── .gitmodules ├── WinMasto ├── Assets │ ├── StoreLogo.png │ ├── Images │ │ └── Icon2.png │ ├── BadgeLogo.scale-100.png │ ├── BadgeLogo.scale-125.png │ ├── BadgeLogo.scale-150.png │ ├── BadgeLogo.scale-200.png │ ├── BadgeLogo.scale-400.png │ ├── LargeTile.scale-100.png │ ├── LargeTile.scale-125.png │ ├── LargeTile.scale-150.png │ ├── LargeTile.scale-200.png │ ├── LargeTile.scale-400.png │ ├── SmallTile.scale-100.png │ ├── SmallTile.scale-125.png │ ├── SmallTile.scale-150.png │ ├── SmallTile.scale-200.png │ ├── SmallTile.scale-400.png │ ├── StoreLogo.scale-100.png │ ├── StoreLogo.scale-125.png │ ├── StoreLogo.scale-150.png │ ├── StoreLogo.scale-200.png │ ├── StoreLogo.scale-400.png │ ├── SplashScreen.scale-100.png │ ├── SplashScreen.scale-125.png │ ├── SplashScreen.scale-150.png │ ├── SplashScreen.scale-200.png │ ├── SplashScreen.scale-400.png │ ├── LockScreenLogo.scale-200.png │ ├── Square150x150Logo.scale-100.png │ ├── Square150x150Logo.scale-125.png │ ├── Square150x150Logo.scale-150.png │ ├── Square150x150Logo.scale-200.png │ ├── Square150x150Logo.scale-400.png │ ├── Square44x44Logo.scale-100.png │ ├── Square44x44Logo.scale-125.png │ ├── Square44x44Logo.scale-150.png │ ├── Square44x44Logo.scale-200.png │ ├── Square44x44Logo.scale-400.png │ ├── Wide310x150Logo.scale-100.png │ ├── Wide310x150Logo.scale-125.png │ ├── Wide310x150Logo.scale-150.png │ ├── Wide310x150Logo.scale-200.png │ ├── Wide310x150Logo.scale-400.png │ ├── Square44x44Logo.targetsize-16.png │ ├── Square44x44Logo.targetsize-24.png │ ├── Square44x44Logo.targetsize-32.png │ ├── Square44x44Logo.targetsize-48.png │ ├── Square44x44Logo.targetsize-256.png │ ├── Square44x44Logo.altform-unplated_targetsize-16.png │ ├── Square44x44Logo.altform-unplated_targetsize-256.png │ ├── Square44x44Logo.altform-unplated_targetsize-32.png │ ├── Square44x44Logo.altform-unplated_targetsize-48.png │ └── Square44x44Logo.targetsize-24_altform-unplated.png ├── WinMasto_TemporaryKey.pfx ├── Models │ ├── NewStatusParameter.cs │ └── PhotoFileInfo.cs ├── ViewModels │ ├── ImageGalleryViewModel.cs │ ├── ShellViewModel.cs │ ├── NotificationPageViewModel.cs │ ├── WinMastoViewModel.cs │ ├── MainPageViewModel.cs │ ├── SettingsPageViewModel.cs │ ├── StatusPageViewModel.cs │ ├── NewStatusPageViewModel.cs │ ├── LoginPageViewModel.cs │ └── AccountPageViewModel.cs ├── Tools │ ├── MessageDialogMaker.cs │ ├── Converters │ │ ├── OpenMenuFlyoutAction.cs │ │ ├── SpoilerIconConverter.cs │ │ ├── AddAtSignConverter.cs │ │ ├── StringToVisibilityConverter.cs │ │ ├── CountVisibilityConverter.cs │ │ ├── BooleanToVisibilityConverter.cs │ │ ├── BooleanToVisibilityInverter.cs │ │ ├── ReplyToStatusConverter.cs │ │ ├── FollowYouConverter.cs │ │ ├── StripHtmlConverter.cs │ │ ├── ImageGalleryVisibilityConverter.cs │ │ ├── CreatedTimeConverter.cs │ │ ├── FavoriteIconConverter.cs │ │ ├── ThumbnailToImageConverter.cs │ │ ├── AccountConverters.cs │ │ └── SpoilerOrNSFWConverter.cs │ ├── TemplateSelector │ │ ├── MediaAttachmentTemplateSelector.cs │ │ ├── StatusTemplateSelector.cs │ │ └── NotificationTemplateSelector.cs │ ├── Files │ │ └── FileAccessCommands.cs │ ├── BackgroundTasks │ │ └── BackgroundTaskUtils.cs │ ├── NotificationScrollingCollection.cs │ └── TimelineScrollingCollection.cs ├── Styles │ ├── Light.xaml │ └── Dark.xaml ├── Views │ ├── LoginPage.xaml.cs │ ├── SettingsPage.xaml.cs │ ├── Busy.xaml │ ├── Splash.xaml │ ├── Splash.xaml.cs │ ├── Busy.xaml.cs │ ├── Shell.xaml.cs │ ├── NewStatusPage.xaml.cs │ ├── LoginPage.xaml │ ├── AccountPage.xaml.cs │ ├── StatusPage.xaml.cs │ ├── MainPage.xaml.cs │ ├── NotificationPage.xaml.cs │ ├── NewStatusPage.xaml │ └── Shell.xaml ├── Properties │ ├── AssemblyInfo.cs │ └── Default.rd.xml ├── App.xaml ├── Package.appxmanifest ├── Brushes │ └── HostBlurBrush.cs ├── Effects │ └── PointLightEffect.cs ├── Controls │ ├── ImageGalleryView.xaml.cs │ └── ImageGalleryView.xaml └── Services │ └── SettingsService.cs ├── WinMasto.Windows.Core ├── Notifications │ └── ToastNotificationArgs.cs ├── Properties │ ├── AssemblyInfo.cs │ └── WinMasto.Windows.Core.rd.xml ├── Extensions │ └── InteractiveText.cs └── WinMasto.Core.csproj ├── LICENSE ├── WinMasto.BackgroundNotify ├── Properties │ └── AssemblyInfo.cs ├── ToastNotificationBackgroundTask.cs ├── BackgroundNotifyStatus.cs └── WinMasto.BackgroundNotify.csproj ├── README.md ├── .gitattributes ├── .gitignore └── WinMasto.sln /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "Mastonet"] 2 | path = Mastonet 3 | url = https://github.com/drasticactions/Mastonet.git 4 | -------------------------------------------------------------------------------- /WinMasto/Assets/StoreLogo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/drasticactions/WinMasto/HEAD/WinMasto/Assets/StoreLogo.png -------------------------------------------------------------------------------- /WinMasto/Assets/Images/Icon2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/drasticactions/WinMasto/HEAD/WinMasto/Assets/Images/Icon2.png -------------------------------------------------------------------------------- /WinMasto/WinMasto_TemporaryKey.pfx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/drasticactions/WinMasto/HEAD/WinMasto/WinMasto_TemporaryKey.pfx -------------------------------------------------------------------------------- /WinMasto/Assets/BadgeLogo.scale-100.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/drasticactions/WinMasto/HEAD/WinMasto/Assets/BadgeLogo.scale-100.png -------------------------------------------------------------------------------- /WinMasto/Assets/BadgeLogo.scale-125.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/drasticactions/WinMasto/HEAD/WinMasto/Assets/BadgeLogo.scale-125.png -------------------------------------------------------------------------------- /WinMasto/Assets/BadgeLogo.scale-150.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/drasticactions/WinMasto/HEAD/WinMasto/Assets/BadgeLogo.scale-150.png -------------------------------------------------------------------------------- /WinMasto/Assets/BadgeLogo.scale-200.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/drasticactions/WinMasto/HEAD/WinMasto/Assets/BadgeLogo.scale-200.png -------------------------------------------------------------------------------- /WinMasto/Assets/BadgeLogo.scale-400.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/drasticactions/WinMasto/HEAD/WinMasto/Assets/BadgeLogo.scale-400.png -------------------------------------------------------------------------------- /WinMasto/Assets/LargeTile.scale-100.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/drasticactions/WinMasto/HEAD/WinMasto/Assets/LargeTile.scale-100.png -------------------------------------------------------------------------------- /WinMasto/Assets/LargeTile.scale-125.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/drasticactions/WinMasto/HEAD/WinMasto/Assets/LargeTile.scale-125.png -------------------------------------------------------------------------------- /WinMasto/Assets/LargeTile.scale-150.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/drasticactions/WinMasto/HEAD/WinMasto/Assets/LargeTile.scale-150.png -------------------------------------------------------------------------------- /WinMasto/Assets/LargeTile.scale-200.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/drasticactions/WinMasto/HEAD/WinMasto/Assets/LargeTile.scale-200.png -------------------------------------------------------------------------------- /WinMasto/Assets/LargeTile.scale-400.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/drasticactions/WinMasto/HEAD/WinMasto/Assets/LargeTile.scale-400.png -------------------------------------------------------------------------------- /WinMasto/Assets/SmallTile.scale-100.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/drasticactions/WinMasto/HEAD/WinMasto/Assets/SmallTile.scale-100.png -------------------------------------------------------------------------------- /WinMasto/Assets/SmallTile.scale-125.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/drasticactions/WinMasto/HEAD/WinMasto/Assets/SmallTile.scale-125.png -------------------------------------------------------------------------------- /WinMasto/Assets/SmallTile.scale-150.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/drasticactions/WinMasto/HEAD/WinMasto/Assets/SmallTile.scale-150.png -------------------------------------------------------------------------------- /WinMasto/Assets/SmallTile.scale-200.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/drasticactions/WinMasto/HEAD/WinMasto/Assets/SmallTile.scale-200.png -------------------------------------------------------------------------------- /WinMasto/Assets/SmallTile.scale-400.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/drasticactions/WinMasto/HEAD/WinMasto/Assets/SmallTile.scale-400.png -------------------------------------------------------------------------------- /WinMasto/Assets/StoreLogo.scale-100.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/drasticactions/WinMasto/HEAD/WinMasto/Assets/StoreLogo.scale-100.png -------------------------------------------------------------------------------- /WinMasto/Assets/StoreLogo.scale-125.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/drasticactions/WinMasto/HEAD/WinMasto/Assets/StoreLogo.scale-125.png -------------------------------------------------------------------------------- /WinMasto/Assets/StoreLogo.scale-150.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/drasticactions/WinMasto/HEAD/WinMasto/Assets/StoreLogo.scale-150.png -------------------------------------------------------------------------------- /WinMasto/Assets/StoreLogo.scale-200.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/drasticactions/WinMasto/HEAD/WinMasto/Assets/StoreLogo.scale-200.png -------------------------------------------------------------------------------- /WinMasto/Assets/StoreLogo.scale-400.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/drasticactions/WinMasto/HEAD/WinMasto/Assets/StoreLogo.scale-400.png -------------------------------------------------------------------------------- /WinMasto/Assets/SplashScreen.scale-100.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/drasticactions/WinMasto/HEAD/WinMasto/Assets/SplashScreen.scale-100.png -------------------------------------------------------------------------------- /WinMasto/Assets/SplashScreen.scale-125.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/drasticactions/WinMasto/HEAD/WinMasto/Assets/SplashScreen.scale-125.png -------------------------------------------------------------------------------- /WinMasto/Assets/SplashScreen.scale-150.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/drasticactions/WinMasto/HEAD/WinMasto/Assets/SplashScreen.scale-150.png -------------------------------------------------------------------------------- /WinMasto/Assets/SplashScreen.scale-200.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/drasticactions/WinMasto/HEAD/WinMasto/Assets/SplashScreen.scale-200.png -------------------------------------------------------------------------------- /WinMasto/Assets/SplashScreen.scale-400.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/drasticactions/WinMasto/HEAD/WinMasto/Assets/SplashScreen.scale-400.png -------------------------------------------------------------------------------- /WinMasto/Assets/LockScreenLogo.scale-200.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/drasticactions/WinMasto/HEAD/WinMasto/Assets/LockScreenLogo.scale-200.png -------------------------------------------------------------------------------- /WinMasto/Assets/Square150x150Logo.scale-100.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/drasticactions/WinMasto/HEAD/WinMasto/Assets/Square150x150Logo.scale-100.png -------------------------------------------------------------------------------- /WinMasto/Assets/Square150x150Logo.scale-125.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/drasticactions/WinMasto/HEAD/WinMasto/Assets/Square150x150Logo.scale-125.png -------------------------------------------------------------------------------- /WinMasto/Assets/Square150x150Logo.scale-150.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/drasticactions/WinMasto/HEAD/WinMasto/Assets/Square150x150Logo.scale-150.png -------------------------------------------------------------------------------- /WinMasto/Assets/Square150x150Logo.scale-200.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/drasticactions/WinMasto/HEAD/WinMasto/Assets/Square150x150Logo.scale-200.png -------------------------------------------------------------------------------- /WinMasto/Assets/Square150x150Logo.scale-400.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/drasticactions/WinMasto/HEAD/WinMasto/Assets/Square150x150Logo.scale-400.png -------------------------------------------------------------------------------- /WinMasto/Assets/Square44x44Logo.scale-100.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/drasticactions/WinMasto/HEAD/WinMasto/Assets/Square44x44Logo.scale-100.png -------------------------------------------------------------------------------- /WinMasto/Assets/Square44x44Logo.scale-125.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/drasticactions/WinMasto/HEAD/WinMasto/Assets/Square44x44Logo.scale-125.png -------------------------------------------------------------------------------- /WinMasto/Assets/Square44x44Logo.scale-150.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/drasticactions/WinMasto/HEAD/WinMasto/Assets/Square44x44Logo.scale-150.png -------------------------------------------------------------------------------- /WinMasto/Assets/Square44x44Logo.scale-200.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/drasticactions/WinMasto/HEAD/WinMasto/Assets/Square44x44Logo.scale-200.png -------------------------------------------------------------------------------- /WinMasto/Assets/Square44x44Logo.scale-400.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/drasticactions/WinMasto/HEAD/WinMasto/Assets/Square44x44Logo.scale-400.png -------------------------------------------------------------------------------- /WinMasto/Assets/Wide310x150Logo.scale-100.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/drasticactions/WinMasto/HEAD/WinMasto/Assets/Wide310x150Logo.scale-100.png -------------------------------------------------------------------------------- /WinMasto/Assets/Wide310x150Logo.scale-125.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/drasticactions/WinMasto/HEAD/WinMasto/Assets/Wide310x150Logo.scale-125.png -------------------------------------------------------------------------------- /WinMasto/Assets/Wide310x150Logo.scale-150.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/drasticactions/WinMasto/HEAD/WinMasto/Assets/Wide310x150Logo.scale-150.png -------------------------------------------------------------------------------- /WinMasto/Assets/Wide310x150Logo.scale-200.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/drasticactions/WinMasto/HEAD/WinMasto/Assets/Wide310x150Logo.scale-200.png -------------------------------------------------------------------------------- /WinMasto/Assets/Wide310x150Logo.scale-400.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/drasticactions/WinMasto/HEAD/WinMasto/Assets/Wide310x150Logo.scale-400.png -------------------------------------------------------------------------------- /WinMasto/Assets/Square44x44Logo.targetsize-16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/drasticactions/WinMasto/HEAD/WinMasto/Assets/Square44x44Logo.targetsize-16.png -------------------------------------------------------------------------------- /WinMasto/Assets/Square44x44Logo.targetsize-24.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/drasticactions/WinMasto/HEAD/WinMasto/Assets/Square44x44Logo.targetsize-24.png -------------------------------------------------------------------------------- /WinMasto/Assets/Square44x44Logo.targetsize-32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/drasticactions/WinMasto/HEAD/WinMasto/Assets/Square44x44Logo.targetsize-32.png -------------------------------------------------------------------------------- /WinMasto/Assets/Square44x44Logo.targetsize-48.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/drasticactions/WinMasto/HEAD/WinMasto/Assets/Square44x44Logo.targetsize-48.png -------------------------------------------------------------------------------- /WinMasto/Assets/Square44x44Logo.targetsize-256.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/drasticactions/WinMasto/HEAD/WinMasto/Assets/Square44x44Logo.targetsize-256.png -------------------------------------------------------------------------------- /WinMasto/Assets/Square44x44Logo.altform-unplated_targetsize-16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/drasticactions/WinMasto/HEAD/WinMasto/Assets/Square44x44Logo.altform-unplated_targetsize-16.png -------------------------------------------------------------------------------- /WinMasto/Assets/Square44x44Logo.altform-unplated_targetsize-256.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/drasticactions/WinMasto/HEAD/WinMasto/Assets/Square44x44Logo.altform-unplated_targetsize-256.png -------------------------------------------------------------------------------- /WinMasto/Assets/Square44x44Logo.altform-unplated_targetsize-32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/drasticactions/WinMasto/HEAD/WinMasto/Assets/Square44x44Logo.altform-unplated_targetsize-32.png -------------------------------------------------------------------------------- /WinMasto/Assets/Square44x44Logo.altform-unplated_targetsize-48.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/drasticactions/WinMasto/HEAD/WinMasto/Assets/Square44x44Logo.altform-unplated_targetsize-48.png -------------------------------------------------------------------------------- /WinMasto/Assets/Square44x44Logo.targetsize-24_altform-unplated.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/drasticactions/WinMasto/HEAD/WinMasto/Assets/Square44x44Logo.targetsize-24_altform-unplated.png -------------------------------------------------------------------------------- /WinMasto/Models/NewStatusParameter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using Mastonet.Entities; 7 | 8 | namespace WinMasto.Models 9 | { 10 | public class NewStatusParameter 11 | { 12 | public Status Status { get; set; } 13 | 14 | public bool IsReply { get; set; } 15 | 16 | public bool IsMention { get; set; } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /WinMasto.Windows.Core/Notifications/ToastNotificationArgs.cs: -------------------------------------------------------------------------------- 1 | using Mastonet.Entities; 2 | 3 | namespace WinMasto.Core.Notifications 4 | { 5 | public class ToastNotificationArgs 6 | { 7 | public ToastType Type { get; set; } 8 | 9 | public Account Account { get; set; } 10 | 11 | public Status Status { get; set; } 12 | } 13 | 14 | public enum ToastType 15 | { 16 | Other, 17 | Ignore, 18 | Sleep, 19 | Account, 20 | Status 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /WinMasto/Models/PhotoFileInfo.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using Windows.Storage; 7 | using Windows.Storage.FileProperties; 8 | using Mastonet.Entities; 9 | 10 | namespace WinMasto.Models 11 | { 12 | public class PhotoFileInfo 13 | { 14 | public StorageFile File { get; set; } 15 | 16 | public StorageItemThumbnail Thumbnail { get; set; } 17 | 18 | public Attachment Attachment { get; set; } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /WinMasto/ViewModels/ImageGalleryViewModel.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using Mastonet.Entities; 7 | 8 | namespace WinMasto.ViewModels 9 | { 10 | public class ImageGalleryViewModel : StatusBaseViewModel 11 | { 12 | private Status _status; 13 | public Status Status { get { return _status; } set { Set(ref _status, value); } } 14 | 15 | public async void SetStatus(Status status, Attachment attachment) 16 | { 17 | await LoginUser(); 18 | Status = status; 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /WinMasto/Tools/MessageDialogMaker.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using Windows.UI.Popups; 7 | 8 | namespace WinMasto.Tools 9 | { 10 | public static class MessageDialogMaker 11 | { 12 | public static async Task SendMessageDialogAsync(string message, bool isSuccess) 13 | { 14 | var title = isSuccess ? "WinMasto: " : "WinMasto - Error: "; 15 | var dialog = new MessageDialog((string.Concat(title, Environment.NewLine, Environment.NewLine, message))); 16 | await dialog.ShowAsync(); 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /WinMasto/Tools/Converters/OpenMenuFlyoutAction.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using Windows.UI.Xaml; 7 | using Windows.UI.Xaml.Controls.Primitives; 8 | using Microsoft.Xaml.Interactivity; 9 | 10 | namespace WinMasto.Tools.Converters 11 | { 12 | public class OpenMenuFlyoutAction : DependencyObject, IAction 13 | { 14 | public object Execute(object sender, object parameter) 15 | { 16 | FrameworkElement senderElement = sender as FrameworkElement; 17 | FlyoutBase flyoutBase = FlyoutBase.GetAttachedFlyout(senderElement); 18 | 19 | flyoutBase.ShowAt(senderElement); 20 | 21 | return null; 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /WinMasto/Tools/Converters/SpoilerIconConverter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using Windows.UI.Xaml.Controls; 7 | using Windows.UI.Xaml.Data; 8 | 9 | namespace WinMasto.Tools.Converters 10 | { 11 | public class SpoilerIconConverter : IValueConverter 12 | { 13 | public object Convert(object value, Type targetType, object parameter, string language) 14 | { 15 | return (bool) value ? Symbol.ProtectedDocument : Symbol.Document; 16 | } 17 | 18 | public object ConvertBack(object value, Type targetType, object parameter, string language) 19 | { 20 | throw new NotImplementedException(); 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /WinMasto/Tools/Converters/AddAtSignConverter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using Windows.UI.Xaml.Data; 7 | 8 | namespace WinMasto.Tools.Converters 9 | { 10 | public class AddAtSignConverter : IValueConverter 11 | { 12 | public object Convert(object value, Type targetType, object parameter, string language) 13 | { 14 | var accountNameValue = value as string; 15 | return accountNameValue == null ? "@error" : $"@{accountNameValue}"; 16 | } 17 | 18 | public object ConvertBack(object value, Type targetType, object parameter, string language) 19 | { 20 | throw new NotImplementedException(); 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /WinMasto/Tools/Converters/StringToVisibilityConverter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using Windows.UI.Xaml; 7 | using Windows.UI.Xaml.Data; 8 | 9 | namespace WinMasto.Tools.Converters 10 | { 11 | public class StringToVisibilityConverter : IValueConverter 12 | { 13 | public object Convert(object value, Type targetType, object parameter, string language) 14 | { 15 | return !string.IsNullOrEmpty((string) value) ? Visibility.Visible : Visibility.Collapsed; 16 | } 17 | 18 | public object ConvertBack(object value, Type targetType, object parameter, string language) 19 | { 20 | throw new NotImplementedException(); 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /WinMasto/Tools/Converters/CountVisibilityConverter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using Windows.UI.Xaml; 7 | using Windows.UI.Xaml.Data; 8 | 9 | namespace WinMasto.Tools.Converters 10 | { 11 | public class CountVisibilityConverter : IValueConverter 12 | { 13 | public object Convert(object value, Type targetType, object parameter, string language) 14 | { 15 | var number = (int) value; 16 | return number > 0 ? Visibility.Visible : Visibility.Collapsed; 17 | } 18 | 19 | public object ConvertBack(object value, Type targetType, object parameter, string language) 20 | { 21 | throw new NotImplementedException(); 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /WinMasto/Tools/Converters/BooleanToVisibilityConverter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using Windows.UI.Xaml; 7 | using Windows.UI.Xaml.Data; 8 | 9 | namespace WinMasto.Tools.Converters 10 | { 11 | public sealed class BooleanToVisibilityConverter : IValueConverter 12 | { 13 | public object Convert(object value, Type targetType, object parameter, string language) 14 | { 15 | return (value is bool && (bool)value) ? Visibility.Visible : Visibility.Collapsed; 16 | } 17 | 18 | public object ConvertBack(object value, Type targetType, object parameter, string language) 19 | { 20 | return value is Visibility && (Visibility)value == Visibility.Visible; 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /WinMasto/Tools/Converters/BooleanToVisibilityInverter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using Windows.UI.Xaml; 7 | using Windows.UI.Xaml.Data; 8 | 9 | namespace WinMasto.Tools.Converters 10 | { 11 | public class BooleanToVisibilityInverter : IValueConverter 12 | { 13 | public object Convert(object value, Type targetType, object parameter, string language) 14 | { 15 | return (value is bool && (bool)value == false) ? Visibility.Visible : Visibility.Collapsed; 16 | } 17 | 18 | public object ConvertBack(object value, Type targetType, object parameter, string language) 19 | { 20 | return value is Visibility && (Visibility)value == Visibility.Visible; 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /WinMasto/Tools/Converters/ReplyToStatusConverter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using Windows.UI.Xaml.Data; 7 | using Mastonet.Entities; 8 | 9 | namespace WinMasto.Tools.Converters 10 | { 11 | public class ReplyToStatusConverter : IValueConverter 12 | { 13 | public object Convert(object value, Type targetType, object parameter, string language) 14 | { 15 | var status = value as Status; 16 | if (status == null) return ""; 17 | return $"↩️ Replying to {status.Account.AccountName}"; 18 | } 19 | 20 | public object ConvertBack(object value, Type targetType, object parameter, string language) 21 | { 22 | throw new NotImplementedException(); 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /WinMasto/Tools/Converters/FollowYouConverter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using Windows.UI.Xaml.Data; 7 | using Mastonet.Entities; 8 | 9 | namespace WinMasto.Tools.Converters 10 | { 11 | public class FollowYouConverter : IValueConverter 12 | { 13 | public object Convert(object value, Type targetType, object parameter, string language) 14 | { 15 | var notification = value as Notification; 16 | if (notification == null) return ""; 17 | return $"@{notification.Account.AccountName} followed you"; 18 | } 19 | 20 | public object ConvertBack(object value, Type targetType, object parameter, string language) 21 | { 22 | throw new NotImplementedException(); 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /WinMasto/Tools/TemplateSelector/MediaAttachmentTemplateSelector.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using Windows.UI.Xaml; 7 | using Windows.UI.Xaml.Controls; 8 | using Mastonet.Entities; 9 | 10 | namespace WinMasto.Tools.TemplateSelector 11 | { 12 | public class MediaAttachmentTemplateSelector : DataTemplateSelector 13 | { 14 | public DataTemplate ImageStatusDataTemplate { get; set; } 15 | 16 | public DataTemplate VideoStatusDataTemplate { get; set; } 17 | 18 | protected override DataTemplate SelectTemplateCore(object item, 19 | DependencyObject container) 20 | { 21 | var status = item as Attachment; 22 | return status.Url.Contains(".mp4") ? VideoStatusDataTemplate : ImageStatusDataTemplate; 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /WinMasto/Tools/Converters/StripHtmlConverter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Net; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | using Windows.UI.Xaml.Data; 8 | using WinMasto.Tools.Extensions; 9 | 10 | namespace WinMasto.Tools.Converters 11 | { 12 | public class StripHtmlConverter : IValueConverter 13 | { 14 | public object Convert(object value, Type targetType, object parameter, string language) 15 | { 16 | var accountNameValue = value as string; 17 | return accountNameValue == null ? value : HtmlRemoval.StripTagsCharArray(WebUtility.HtmlDecode(accountNameValue)); 18 | } 19 | 20 | public object ConvertBack(object value, Type targetType, object parameter, string language) 21 | { 22 | throw new NotImplementedException(); 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /WinMasto/Tools/Converters/ImageGalleryVisibilityConverter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using Windows.UI.Xaml; 7 | using Windows.UI.Xaml.Data; 8 | using Mastonet.Entities; 9 | 10 | namespace WinMasto.Tools.Converters 11 | { 12 | public class ImageGalleryVisibilityConverter : IValueConverter 13 | { 14 | public object Convert(object value, Type targetType, object parameter, string language) 15 | { 16 | var attachments = value as IEnumerable; 17 | if (attachments == null) return Visibility.Collapsed; 18 | return attachments.Any() ? Visibility.Visible : Visibility.Collapsed; 19 | } 20 | 21 | public object ConvertBack(object value, Type targetType, object parameter, string language) 22 | { 23 | throw new NotImplementedException(); 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /WinMasto/Tools/Converters/CreatedTimeConverter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using Windows.UI.Xaml.Data; 7 | using PrettyPrintNet; 8 | 9 | namespace WinMasto.Tools.Converters 10 | { 11 | public class CreatedTimeConverter : IValueConverter 12 | { 13 | public object Convert(object value, Type targetType, object parameter, string language) 14 | { 15 | var accountDateTime = (DateTime) value; 16 | return accountDateTime.ToLocalTime().ToString("g"); 17 | //var timespan = DateTime.UtcNow.Subtract(accountDateTime); 18 | //return timespan.ToPrettyString(2, UnitStringRepresentation.Compact); 19 | } 20 | 21 | public object ConvertBack(object value, Type targetType, object parameter, string language) 22 | { 23 | throw new NotImplementedException(); 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /WinMasto/Tools/TemplateSelector/StatusTemplateSelector.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using Windows.UI.Xaml; 7 | using Windows.UI.Xaml.Controls; 8 | using Mastonet.Entities; 9 | 10 | namespace WinMasto.Tools.TemplateSelector 11 | { 12 | public class StatusTemplateSelector : DataTemplateSelector 13 | { 14 | public DataTemplate RegularStatusDataTemplate { get; set; } 15 | 16 | public DataTemplate ReblogStatusDataTemplate { get; set; } 17 | 18 | protected override DataTemplate SelectTemplateCore(object item, 19 | DependencyObject container) 20 | { 21 | var status = item as Status; 22 | if (status == null) return RegularStatusDataTemplate; 23 | 24 | if (status.Reblog != null) return ReblogStatusDataTemplate; 25 | 26 | return RegularStatusDataTemplate; 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /WinMasto/Styles/Light.xaml: -------------------------------------------------------------------------------- 1 | 5 | 6 | #E5E5E5 7 | #FFFFFF 8 | #000000 9 | White 10 | Black 11 | Black 12 | Black 13 | Black 14 | Black 15 | White 16 | 17 | -------------------------------------------------------------------------------- /WinMasto/Styles/Dark.xaml: -------------------------------------------------------------------------------- 1 | 5 | #000000 6 | #FFFFFF 7 | Black 8 | #2B2B2B 9 | #FFFFFF 10 | 11 | White 12 | White 13 | White 14 | White 15 | #2B2B2B 16 | 17 | -------------------------------------------------------------------------------- /WinMasto/Tools/Converters/FavoriteIconConverter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using Windows.UI.Xaml.Data; 7 | using FontAwesome.UWP; 8 | using Windows.UI.Xaml.Controls; 9 | 10 | namespace WinMasto.Tools.Converters 11 | { 12 | public class FavoriteIconConverter : IValueConverter 13 | { 14 | public object Convert(object value, Type targetType, object parameter, string language) 15 | { 16 | try 17 | { 18 | var favorited = (bool) value; 19 | return favorited ? Symbol.SolidStar : Symbol.OutlineStar; 20 | } 21 | catch (Exception e) 22 | { 23 | return Symbol.OutlineStar; 24 | } 25 | } 26 | 27 | public object ConvertBack(object value, Type targetType, object parameter, string language) 28 | { 29 | throw new NotImplementedException(); 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /WinMasto/Tools/Files/FileAccessCommands.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.IO; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | using Windows.Storage; 8 | 9 | namespace WinMasto.Tools.Files 10 | { 11 | public class FileAccessCommands 12 | { 13 | public static async Task SaveStreamToCameraRoll(Stream streamToSave, string fileName) 14 | { 15 | var file = await KnownFolders.CameraRoll.CreateFileAsync(fileName, CreationCollisionOption.ReplaceExisting); 16 | using (var fileStream = await file.OpenStreamForWriteAsync()) 17 | { 18 | const int bufferSize = 1024; 19 | var buf = new byte[bufferSize]; 20 | 21 | var bytesread = 0; 22 | while ((bytesread = await streamToSave.ReadAsync(buf, 0, bufferSize)) > 0) 23 | { 24 | await fileStream.WriteAsync(buf, 0, bytesread); 25 | } 26 | } 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /WinMasto/ViewModels/ShellViewModel.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using Template10.Mvvm; 7 | using WinMasto.Services; 8 | 9 | namespace WinMasto.ViewModels 10 | { 11 | public class ShellViewModel : WinMastoViewModel 12 | { 13 | #region Properties 14 | //private UserAuth _user = default(UserAuth); 15 | 16 | //public UserAuth User 17 | //{ 18 | // get { return _user; } 19 | // set 20 | // { 21 | // Set(ref _user, value); 22 | // } 23 | //} 24 | #endregion 25 | 26 | #region Methods 27 | 28 | public void CheckLogin() 29 | { 30 | try 31 | { 32 | IsLoggedIn = SettingsService.Instance.UserAccount != null; 33 | } 34 | catch (Exception) 35 | { 36 | return; 37 | } 38 | } 39 | 40 | #endregion 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /WinMasto/Views/LoginPage.xaml.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.IO; 4 | using System.Linq; 5 | using System.Runtime.InteropServices.WindowsRuntime; 6 | using Windows.Foundation; 7 | using Windows.Foundation.Collections; 8 | using Windows.UI.Xaml; 9 | using Windows.UI.Xaml.Controls; 10 | using Windows.UI.Xaml.Controls.Primitives; 11 | using Windows.UI.Xaml.Data; 12 | using Windows.UI.Xaml.Input; 13 | using Windows.UI.Xaml.Media; 14 | using Windows.UI.Xaml.Navigation; 15 | using WinMasto.ViewModels; 16 | 17 | // The Blank Page item template is documented at https://go.microsoft.com/fwlink/?LinkId=234238 18 | 19 | namespace WinMasto.Views 20 | { 21 | /// 22 | /// An empty page that can be used on its own or navigated to within a Frame. 23 | /// 24 | public sealed partial class LoginPage : Page 25 | { 26 | public LoginPage() 27 | { 28 | this.InitializeComponent(); 29 | } 30 | 31 | public LoginPageViewModel ViewModel => this.DataContext as LoginPageViewModel; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /WinMasto/Views/SettingsPage.xaml.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.IO; 4 | using System.Linq; 5 | using System.Runtime.InteropServices.WindowsRuntime; 6 | using Windows.Foundation; 7 | using Windows.Foundation.Collections; 8 | using Windows.UI.Xaml; 9 | using Windows.UI.Xaml.Controls; 10 | using Windows.UI.Xaml.Controls.Primitives; 11 | using Windows.UI.Xaml.Data; 12 | using Windows.UI.Xaml.Input; 13 | using Windows.UI.Xaml.Media; 14 | using Windows.UI.Xaml.Navigation; 15 | using WinMasto.ViewModels; 16 | 17 | // The Blank Page item template is documented at https://go.microsoft.com/fwlink/?LinkId=234238 18 | 19 | namespace WinMasto.Views 20 | { 21 | /// 22 | /// An empty page that can be used on its own or navigated to within a Frame. 23 | /// 24 | public sealed partial class SettingsPage : Page 25 | { 26 | public SettingsPage() 27 | { 28 | this.InitializeComponent(); 29 | } 30 | 31 | public SettingsPageViewModel ViewModel => this.DataContext as SettingsPageViewModel; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 Awful 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /WinMasto/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("WinMasto")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("WinMasto")] 13 | [assembly: AssemblyCopyright("Copyright © 2017")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Version information for an assembly consists of the following four values: 18 | // 19 | // Major Version 20 | // Minor Version 21 | // Build Number 22 | // Revision 23 | // 24 | // You can specify all the values or you can default the Build and Revision Numbers 25 | // by using the '*' as shown below: 26 | // [assembly: AssemblyVersion("1.0.*")] 27 | [assembly: AssemblyVersion("1.0.0.0")] 28 | [assembly: AssemblyFileVersion("1.0.0.0")] 29 | [assembly: ComVisible(false)] -------------------------------------------------------------------------------- /WinMasto.Windows.Core/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("WinMasto.Windows.Core")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("WinMasto.Windows.Core")] 13 | [assembly: AssemblyCopyright("Copyright © 2017")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Version information for an assembly consists of the following four values: 18 | // 19 | // Major Version 20 | // Minor Version 21 | // Build Number 22 | // Revision 23 | // 24 | // You can specify all the values or you can default the Build and Revision Numbers 25 | // by using the '*' as shown below: 26 | // [assembly: AssemblyVersion("1.0.*")] 27 | [assembly: AssemblyVersion("1.0.0.0")] 28 | [assembly: AssemblyFileVersion("1.0.0.0")] 29 | [assembly: ComVisible(false)] -------------------------------------------------------------------------------- /WinMasto/Views/Busy.xaml: -------------------------------------------------------------------------------- 1 | 11 | 12 | 14 | 15 | 16 | 17 | 18 | 19 | 21 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /WinMasto.BackgroundNotify/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("WinMasto.BackgroundNotify")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("WinMasto.BackgroundNotify")] 13 | [assembly: AssemblyCopyright("Copyright © 2017")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Version information for an assembly consists of the following four values: 18 | // 19 | // Major Version 20 | // Minor Version 21 | // Build Number 22 | // Revision 23 | // 24 | // You can specify all the values or you can default the Build and Revision Numbers 25 | // by using the '*' as shown below: 26 | // [assembly: AssemblyVersion("1.0.*")] 27 | [assembly: AssemblyVersion("1.0.0.0")] 28 | [assembly: AssemblyFileVersion("1.0.0.0")] 29 | [assembly: ComVisible(false)] -------------------------------------------------------------------------------- /WinMasto/Tools/Converters/ThumbnailToImageConverter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using Windows.Storage.FileProperties; 7 | using Windows.UI.Xaml.Data; 8 | using Windows.UI.Xaml.Media; 9 | using Windows.UI.Xaml.Media.Imaging; 10 | 11 | namespace WinMasto.Tools.Converters 12 | { 13 | public class ThumbnailToImageConverter : IValueConverter 14 | { 15 | public object Convert(object value, Type targetType, object parameter, string language) 16 | { 17 | BitmapImage image = null; 18 | if (value != null) 19 | { 20 | if (value.GetType() != typeof(StorageItemThumbnail)) 21 | { 22 | throw new ArgumentException("Expected a thumbnail"); 23 | } 24 | StorageItemThumbnail thumbnail = (StorageItemThumbnail)value; 25 | image = new BitmapImage(); 26 | image.SetSource(thumbnail); 27 | } 28 | return (image); 29 | } 30 | 31 | public object ConvertBack(object value, Type targetType, object parameter, string language) 32 | { 33 | throw new NotImplementedException(); 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /WinMasto.Windows.Core/Extensions/InteractiveText.cs: -------------------------------------------------------------------------------- 1 | namespace WinMasto.Core.Extensions 2 | { 3 | public static class HtmlRemoval 4 | { 5 | public static string StripTagsCharArray(string source) 6 | { 7 | char[] array = new char[source.Length]; 8 | int arrayIndex = 0; 9 | bool inside = false; 10 | 11 | for (int i = 0; i < source.Length; i++) 12 | { 13 | char let = source[i]; 14 | if (let == '<') 15 | { 16 | inside = true; 17 | continue; 18 | } 19 | if (let == '>') 20 | { 21 | inside = false; 22 | continue; 23 | } 24 | if (!inside) 25 | { 26 | array[arrayIndex] = let; 27 | arrayIndex++; 28 | } 29 | } 30 | return new string(array, 0, arrayIndex); 31 | } 32 | } 33 | 34 | public static class StringExtensions 35 | { 36 | public static string Truncate(this string s, int length) 37 | { 38 | if (s.Length > length) return s.Substring(0, length); 39 | return s; 40 | } 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /WinMasto/ViewModels/NotificationPageViewModel.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using Windows.UI.Xaml.Navigation; 7 | using Template10.Services.NavigationService; 8 | using WinMasto.Tools; 9 | 10 | namespace WinMasto.ViewModels 11 | { 12 | public class NotificationPageViewModel : StatusBaseViewModel 13 | { 14 | public override async Task OnNavigatedToAsync(object parameter, NavigationMode mode, IDictionary suspensionState) 15 | { 16 | IsLoading = true; 17 | Title = "Notifications"; 18 | await LoginUser(); 19 | if (IsLoggedIn) 20 | { 21 | 22 | if (mode == NavigationMode.New || Notifications == null) 23 | { 24 | Notifications = new NotificationScrollingCollection(Client); 25 | } 26 | RaisePropertyChanged("Notifications"); 27 | } 28 | IsLoading = false; 29 | } 30 | 31 | public override Task OnNavigatingFromAsync(NavigatingEventArgs args) 32 | { 33 | if (IsLoggedIn) 34 | { 35 | } 36 | 37 | return base.OnNavigatingFromAsync(args); 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /WinMasto.BackgroundNotify/ToastNotificationBackgroundTask.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using Windows.ApplicationModel.Background; 7 | using Windows.UI.Notifications; 8 | using Newtonsoft.Json; 9 | using Template10.Services.SettingsService; 10 | using WinMasto.Core.Notifications; 11 | 12 | namespace WinMasto.BackgroundNotify 13 | { 14 | public sealed class ToastNotificationBackgroundTask : IBackgroundTask 15 | { 16 | 17 | public void Run(IBackgroundTaskInstance taskInstance) 18 | { 19 | BackgroundTaskDeferral deferral = taskInstance.GetDeferral(); 20 | Template10.Services.SettingsService.ISettingsHelper _helper = new SettingsHelper(); 21 | 22 | var details = taskInstance.TriggerDetails as ToastNotificationActionTriggerDetail; 23 | var arguments = details?.Argument; 24 | if (arguments != null) 25 | { 26 | var args = JsonConvert.DeserializeObject(arguments); 27 | if (args.Type == ToastType.Sleep) 28 | { 29 | _helper.Write("ToastNotifications", false); 30 | } 31 | } 32 | 33 | deferral.Complete(); 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /WinMasto/Properties/Default.rd.xml: -------------------------------------------------------------------------------- 1 | 17 | 18 | 19 | 20 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /WinMasto/Tools/TemplateSelector/NotificationTemplateSelector.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using Windows.UI.Xaml; 7 | using Windows.UI.Xaml.Controls; 8 | using Mastonet.Entities; 9 | 10 | namespace WinMasto.Tools.TemplateSelector 11 | { 12 | public class NotificationTemplateSelector : DataTemplateSelector 13 | { 14 | 15 | public DataTemplate ReblogNotificationDataTemplate { get; set; } 16 | 17 | public DataTemplate MentionNotificationDataTemplate { get; set; } 18 | 19 | public DataTemplate FavouriteNotificationDataTemplate { get; set; } 20 | 21 | public DataTemplate FollowNotificationDataTemplate { get; set; } 22 | 23 | protected override DataTemplate SelectTemplateCore(object item, 24 | DependencyObject container) 25 | { 26 | var notification = item as Notification; 27 | if (notification == null) return MentionNotificationDataTemplate; 28 | 29 | switch (notification.Type) 30 | { 31 | case "mention": 32 | return MentionNotificationDataTemplate; 33 | case "reblog": 34 | return ReblogNotificationDataTemplate; 35 | case "favourite": 36 | return FavouriteNotificationDataTemplate; 37 | case "follow": 38 | return FollowNotificationDataTemplate; 39 | default: 40 | return MentionNotificationDataTemplate; 41 | } 42 | } 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /WinMasto/Views/Splash.xaml: -------------------------------------------------------------------------------- 1 | 11 | 12 | 13 | 14 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | -------------------------------------------------------------------------------- /WinMasto.Windows.Core/Properties/WinMasto.Windows.Core.rd.xml: -------------------------------------------------------------------------------- 1 | 2 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /WinMasto/ViewModels/WinMastoViewModel.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using Mastonet; 7 | using Mastonet.Entities; 8 | using Template10.Mvvm; 9 | using WinMasto.Services; 10 | 11 | namespace WinMasto.ViewModels 12 | { 13 | public class WinMastoViewModel : ViewModelBase 14 | { 15 | public MastodonClient Client { get; set; } 16 | 17 | private bool _isLoggedIn = default(bool); 18 | 19 | public bool IsLoggedIn 20 | { 21 | get => _isLoggedIn; 22 | set => Set(ref _isLoggedIn, value); 23 | } 24 | 25 | private bool _isLoading = default(bool); 26 | 27 | public bool IsLoading 28 | { 29 | get { return _isLoading; } 30 | set 31 | { 32 | Set(ref _isLoading, value); 33 | } 34 | } 35 | 36 | #region User 37 | 38 | private Account _userAccount; 39 | 40 | public Account UserAccount 41 | { 42 | get => _userAccount; 43 | set => Set(ref _userAccount, value); 44 | } 45 | 46 | #endregion 47 | 48 | public async Task LoginUser() 49 | { 50 | var appRegistration = SettingsService.Instance.AppRegistrationService; 51 | var userAuth = SettingsService.Instance.UserAuth; 52 | var instance = SettingsService.Instance.ServerInstance; 53 | if (appRegistration == null || userAuth == null) return; 54 | appRegistration.Instance = instance; 55 | Client = new MastodonClient(appRegistration, new Auth(){ AccessToken = userAuth.AccessToken }); 56 | UserAccount = SettingsService.Instance.UserAccount; 57 | IsLoggedIn = true; 58 | } 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ![](http://i.imgur.com/WmVs4uX.png) 2 | 3 | ## WinMasto 4 | 5 | WinMasto is a UWP client for Mastodon, a GNU social-compatible federated social network. You can learn more about Mastodon [here](https://github.com/tootsuite/mastodon). The goal of this project is to create a simple, elegant, Mastodon client that doesn't try to stuff as many power user features in as possible. 6 | 7 | 8 | 9 | 10 | You can download WinMasto from the [Windows Store](https://www.microsoft.com/store/apps/9p2zk5mb8v7f). You can also sideload debug versions by using the [Releases](https://github.com/drasticactions/WinMasto/releases) tab. 11 | 12 | ## Features 13 | 14 | * Background Task support, including Live Tiles and Toasts 15 | * Most major Mastodon functions should be working, including: 16 | * Posting, including setting visibility and content warnings and attaching images 17 | * Boosting and favoriting posts 18 | * Following and unfollowing 19 | * Notifications 20 | * Home, Local, and Federated timelines 21 | * Dark and light themes 22 | 23 | I'm working on more features, such as 24 | - Push Notifications 25 | - Search 26 | - Fixing the bugs that are probably on the top list 27 | - Tweaking the UI 28 | - Translations 29 | - And more 30 | 31 | ## Contributions 32 | 33 | Open a GitHub issue for bugs, feature requests, etc. I work on this app in my spare time, so I may not be able to fix or add new features, but if anyone else wants to help out, you can send a pull request, and I'll be happy to look at it. 34 | 35 | ## Building 36 | 37 | To build WinMasto, you'll need: 38 | 39 | - Windows 10 (1703, AKA Redstone 2, AKA Creators Update) 40 | - Visual Studio 2017 41 | 42 | Pull down the Mastonet submodule, open the WinMasto solution, and you should be able just to build it. 43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /WinMasto/Views/Splash.xaml.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.IO; 4 | using System.Linq; 5 | using System.Runtime.InteropServices.WindowsRuntime; 6 | using Windows.ApplicationModel.Activation; 7 | using Windows.Foundation; 8 | using Windows.Foundation.Collections; 9 | using Windows.UI.Xaml; 10 | using Windows.UI.Xaml.Controls; 11 | using Windows.UI.Xaml.Controls.Primitives; 12 | using Windows.UI.Xaml.Data; 13 | using Windows.UI.Xaml.Input; 14 | using Windows.UI.Xaml.Media; 15 | using Windows.UI.Xaml.Navigation; 16 | 17 | // The User Control item template is documented at https://go.microsoft.com/fwlink/?LinkId=234236 18 | 19 | namespace WinMasto.Views 20 | { 21 | public sealed partial class Splash : UserControl 22 | { 23 | public Splash(SplashScreen splashScreen) 24 | { 25 | InitializeComponent(); 26 | Window.Current.SizeChanged += (s, e) => Resize(splashScreen); 27 | Resize(splashScreen); 28 | Opacity = 0; 29 | } 30 | 31 | private void Resize(SplashScreen splashScreen) 32 | { 33 | if (splashScreen.ImageLocation.Top == 0) 34 | { 35 | splashImage.Visibility = Visibility.Collapsed; 36 | return; 37 | } 38 | else 39 | { 40 | rootCanvas.Background = null; 41 | splashImage.Visibility = Visibility.Visible; 42 | } 43 | splashImage.Height = splashScreen.ImageLocation.Height; 44 | splashImage.Width = splashScreen.ImageLocation.Width; 45 | splashImage.SetValue(Canvas.TopProperty, splashScreen.ImageLocation.Top); 46 | splashImage.SetValue(Canvas.LeftProperty, splashScreen.ImageLocation.Left); 47 | ProgressTransform.TranslateY = splashImage.Height / 2; 48 | } 49 | 50 | private void Image_Loaded(object sender, RoutedEventArgs e) 51 | { 52 | Opacity = 1; 53 | } 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /WinMasto/Tools/Converters/AccountConverters.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using Windows.UI.Xaml.Data; 7 | using FontAwesome.UWP; 8 | using Mastonet.Entities; 9 | 10 | namespace WinMasto.Tools.Converters 11 | { 12 | public class IsFollowingConverter : IValueConverter 13 | { 14 | public object Convert(object value, Type targetType, object parameter, string language) 15 | { 16 | var relationship = value as Relationship; 17 | if (relationship == null) return null; 18 | return relationship.Following ? FontAwesomeIcon.MinusCircle : FontAwesomeIcon.PlusCircle; 19 | } 20 | 21 | public object ConvertBack(object value, Type targetType, object parameter, string language) 22 | { 23 | throw new NotImplementedException(); 24 | } 25 | } 26 | 27 | public class IsMutedConverter : IValueConverter 28 | { 29 | public object Convert(object value, Type targetType, object parameter, string language) 30 | { 31 | var relationship = value as Relationship; 32 | if (relationship == null) return null; 33 | return relationship.Muting ? FontAwesomeIcon.Microphone : FontAwesomeIcon.MicrophoneSlash; 34 | } 35 | 36 | public object ConvertBack(object value, Type targetType, object parameter, string language) 37 | { 38 | throw new NotImplementedException(); 39 | } 40 | } 41 | 42 | public class IsBlockingConverter : IValueConverter 43 | { 44 | public object Convert(object value, Type targetType, object parameter, string language) 45 | { 46 | var relationship = value as Relationship; 47 | if (relationship == null) return null; 48 | return relationship.Blocking ? FontAwesomeIcon.Unlock : FontAwesomeIcon.Lock; 49 | } 50 | 51 | public object ConvertBack(object value, Type targetType, object parameter, string language) 52 | { 53 | throw new NotImplementedException(); 54 | } 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /WinMasto/Views/Busy.xaml.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.IO; 4 | using System.Linq; 5 | using System.Runtime.InteropServices.WindowsRuntime; 6 | using Windows.Foundation; 7 | using Windows.Foundation.Collections; 8 | using Windows.UI.Xaml; 9 | using Windows.UI.Xaml.Controls; 10 | using Windows.UI.Xaml.Controls.Primitives; 11 | using Windows.UI.Xaml.Data; 12 | using Windows.UI.Xaml.Input; 13 | using Windows.UI.Xaml.Media; 14 | using Windows.UI.Xaml.Navigation; 15 | using Template10.Common; 16 | using Template10.Controls; 17 | 18 | // The User Control item template is documented at https://go.microsoft.com/fwlink/?LinkId=234236 19 | 20 | namespace WinMasto.Views 21 | { 22 | public sealed partial class Busy : UserControl 23 | { 24 | public Busy() 25 | { 26 | InitializeComponent(); 27 | } 28 | 29 | public string BusyText 30 | { 31 | get { return (string)GetValue(BusyTextProperty); } 32 | set { SetValue(BusyTextProperty, value); } 33 | } 34 | public static readonly DependencyProperty BusyTextProperty = 35 | DependencyProperty.Register(nameof(BusyText), typeof(string), typeof(Busy), new PropertyMetadata("Please wait...")); 36 | 37 | public bool IsBusy 38 | { 39 | get { return (bool)GetValue(IsBusyProperty); } 40 | set { SetValue(IsBusyProperty, value); } 41 | } 42 | public static readonly DependencyProperty IsBusyProperty = 43 | DependencyProperty.Register(nameof(IsBusy), typeof(bool), typeof(Busy), new PropertyMetadata(false)); 44 | 45 | // hide and show busy dialog 46 | public static void SetBusy(bool busy, string text = null) 47 | { 48 | WindowWrapper.Current().Dispatcher.Dispatch(() => 49 | { 50 | var modal = Window.Current.Content as ModalDialog; 51 | var view = modal.ModalContent as Busy; 52 | if (view == null) 53 | modal.ModalContent = view = new Busy(); 54 | modal.IsModal = view.IsBusy = busy; 55 | view.BusyText = text; 56 | }); 57 | } 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /WinMasto/ViewModels/MainPageViewModel.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Collections.ObjectModel; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | using Windows.UI.Xaml; 8 | using Windows.UI.Xaml.Controls; 9 | using Windows.UI.Xaml.Navigation; 10 | using Mastonet; 11 | using Mastonet.Entities; 12 | using Template10.Services.NavigationService; 13 | using Template10.Utils; 14 | using WinMasto.Tools; 15 | using WinMasto.Views; 16 | 17 | namespace WinMasto.ViewModels 18 | { 19 | public class MainPageViewModel : StatusBaseViewModel 20 | { 21 | public override async Task OnNavigatedToAsync(object parameter, NavigationMode mode, IDictionary suspensionState) 22 | { 23 | IsLoading = true; 24 | var path = (string)parameter; 25 | if (path == null) path = "home"; 26 | SetTitle(path); 27 | await LoginUser(); 28 | if (IsLoggedIn) 29 | { 30 | 31 | if (mode == NavigationMode.New || (mode == NavigationMode.Back && path != _path)) 32 | { 33 | _path = path; 34 | Statuses = new TimelineScrollingCollection(Client, path); 35 | } 36 | RaisePropertyChanged("Statuses"); 37 | } 38 | IsLoading = false; 39 | } 40 | 41 | private void SetTitle(string path) 42 | { 43 | switch (path) 44 | { 45 | case "home": 46 | Title = "Home Timeline"; 47 | break; 48 | case "public": 49 | Title = "Federated Timeline"; 50 | break; 51 | case "local": 52 | Title = "Local Timeline"; 53 | break; 54 | default: 55 | Title = "Home Timeline"; 56 | break; 57 | } 58 | } 59 | 60 | public override Task OnNavigatingFromAsync(NavigatingEventArgs args) 61 | { 62 | if (IsLoggedIn) 63 | { 64 | } 65 | 66 | return base.OnNavigatingFromAsync(args); 67 | } 68 | 69 | 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /WinMasto/App.xaml: -------------------------------------------------------------------------------- 1 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | -------------------------------------------------------------------------------- /WinMasto/Package.appxmanifest: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | WinMasto 7 | Tim Miller 8 | Assets\StoreLogo.png 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | ############################################################################### 2 | # Set default behavior to automatically normalize line endings. 3 | ############################################################################### 4 | * text=auto 5 | 6 | ############################################################################### 7 | # Set default behavior for command prompt diff. 8 | # 9 | # This is need for earlier builds of msysgit that does not have it on by 10 | # default for csharp files. 11 | # Note: This is only used by command line 12 | ############################################################################### 13 | #*.cs diff=csharp 14 | 15 | ############################################################################### 16 | # Set the merge driver for project and solution files 17 | # 18 | # Merging from the command prompt will add diff markers to the files if there 19 | # are conflicts (Merging from VS is not affected by the settings below, in VS 20 | # the diff markers are never inserted). Diff markers may cause the following 21 | # file extensions to fail to load in VS. An alternative would be to treat 22 | # these files as binary and thus will always conflict and require user 23 | # intervention with every merge. To do so, just uncomment the entries below 24 | ############################################################################### 25 | #*.sln merge=binary 26 | #*.csproj merge=binary 27 | #*.vbproj merge=binary 28 | #*.vcxproj merge=binary 29 | #*.vcproj merge=binary 30 | #*.dbproj merge=binary 31 | #*.fsproj merge=binary 32 | #*.lsproj merge=binary 33 | #*.wixproj merge=binary 34 | #*.modelproj merge=binary 35 | #*.sqlproj merge=binary 36 | #*.wwaproj merge=binary 37 | 38 | ############################################################################### 39 | # behavior for image files 40 | # 41 | # image files are treated as binary by default. 42 | ############################################################################### 43 | #*.jpg binary 44 | #*.png binary 45 | #*.gif binary 46 | 47 | ############################################################################### 48 | # diff behavior for common document formats 49 | # 50 | # Convert binary document formats to text before diffing them. This feature 51 | # is only available from the command line. Turn it on by uncommenting the 52 | # entries below. 53 | ############################################################################### 54 | #*.doc diff=astextplain 55 | #*.DOC diff=astextplain 56 | #*.docx diff=astextplain 57 | #*.DOCX diff=astextplain 58 | #*.dot diff=astextplain 59 | #*.DOT diff=astextplain 60 | #*.pdf diff=astextplain 61 | #*.PDF diff=astextplain 62 | #*.rtf diff=astextplain 63 | #*.RTF diff=astextplain 64 | -------------------------------------------------------------------------------- /WinMasto/ViewModels/SettingsPageViewModel.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using Windows.UI.Xaml; 7 | 8 | namespace WinMasto.ViewModels 9 | { 10 | public class SettingsPageViewModel : WinMastoViewModel 11 | { 12 | public SettingsPartViewModel SettingsPartViewModel { get; } = new SettingsPartViewModel(); 13 | public AboutPartViewModel AboutPartViewModel { get; } = new AboutPartViewModel(); 14 | } 15 | 16 | public class SettingsPartViewModel : WinMastoViewModel 17 | { 18 | readonly Services.SettingsService _settings; 19 | 20 | public SettingsPartViewModel() 21 | { 22 | if (!Windows.ApplicationModel.DesignMode.DesignModeEnabled) 23 | _settings = Services.SettingsService.Instance; 24 | } 25 | 26 | public bool UseDarkThemeButton 27 | { 28 | get { return _settings.AppTheme.Equals(ApplicationTheme.Dark); } 29 | set { _settings.AppTheme = value ? ApplicationTheme.Dark : ApplicationTheme.Light; base.RaisePropertyChanged(); } 30 | } 31 | 32 | public bool UseBackgroundTask 33 | { 34 | get { return _settings.BackgroundEnable; } 35 | set { _settings.BackgroundEnable = value; base.RaisePropertyChanged(); } 36 | } 37 | 38 | public bool UseBackgroundLiveTile 39 | { 40 | get { return _settings.BackgroundTile; } 41 | set { _settings.BackgroundTile = value; base.RaisePropertyChanged(); } 42 | } 43 | 44 | public bool AlwaysShowNSFW 45 | { 46 | get { return _settings.AlwaysShowNSFW; } 47 | set { _settings.AlwaysShowNSFW = value; base.RaisePropertyChanged(); } 48 | } 49 | 50 | public bool UseBackgroundNotify 51 | { 52 | get { return _settings.ToastNotifications; } 53 | set { _settings.ToastNotifications = value; base.RaisePropertyChanged(); } 54 | } 55 | } 56 | 57 | public class AboutPartViewModel : WinMastoViewModel 58 | { 59 | public Uri Logo => Windows.ApplicationModel.Package.Current.Logo; 60 | 61 | public string DisplayName => Windows.ApplicationModel.Package.Current.DisplayName; 62 | 63 | public string Publisher => Windows.ApplicationModel.Package.Current.PublisherDisplayName; 64 | 65 | public string Version 66 | { 67 | get 68 | { 69 | var ver = Windows.ApplicationModel.Package.Current.Id.Version; 70 | return ver.Major.ToString() + "." + ver.Minor.ToString() + "." + ver.Build.ToString() + "." + ver.Revision.ToString(); 71 | } 72 | } 73 | 74 | public Uri RateMe => new Uri("https://github.com/drasticactions/winmasto"); 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /WinMasto/Tools/BackgroundTasks/BackgroundTaskUtils.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Threading.Tasks; 3 | using Windows.ApplicationModel.Background; 4 | using Windows.Storage; 5 | 6 | namespace WinMasto.Tools.BackgroundTasks 7 | { 8 | public class BackgroundTaskUtils 9 | { 10 | public const string BackgroundTaskEntryPoint = "WinMasto.BackgroundNotify.BackgroundNotifyStatus"; 11 | public const string BackgroundTaskName = "BackgroundNotifyStatus"; 12 | public const string ToastBackgroundTaskEntryPoint = "WinMasto.BackgroundNotify.ToastNotificationBackgroundTask"; 13 | public const string ToastBackgroundTaskName = "ToastNotificationBackgroundTask"; 14 | public static string BackgroundTaskProgress = string.Empty; 15 | public static bool BackgroundTaskRegistered = false; 16 | 17 | public static async Task RegisterBackgroundTask(string taskEntryPoint, string name, 18 | IBackgroundTrigger trigger, IBackgroundCondition condition) 19 | { 20 | var builder = new BackgroundTaskBuilder { Name = name, TaskEntryPoint = taskEntryPoint }; 21 | 22 | builder.SetTrigger(trigger); 23 | 24 | 25 | if (condition != null) 26 | { 27 | builder.AddCondition(condition); 28 | } 29 | 30 | BackgroundAccessStatus status = await BackgroundExecutionManager.RequestAccessAsync(); 31 | BackgroundTaskRegistration task = builder.Register(); 32 | return task; 33 | } 34 | 35 | public static void UnregisterBackgroundTasks(string name) 36 | { 37 | foreach (var cur in BackgroundTaskRegistration.AllTasks) 38 | { 39 | if (cur.Value.Name == name) 40 | { 41 | cur.Value.Unregister(true); 42 | } 43 | } 44 | 45 | UpdateBackgroundTaskStatus(name, false); 46 | } 47 | 48 | public static void UpdateBackgroundTaskStatus(string name, bool registered) 49 | { 50 | switch (name) 51 | { 52 | case BackgroundTaskName: 53 | BackgroundTaskRegistered = registered; 54 | break; 55 | } 56 | } 57 | 58 | public static string GetBackgroundTaskStatus(string name) 59 | { 60 | bool registered = false; 61 | switch (name) 62 | { 63 | case BackgroundTaskName: 64 | registered = BackgroundTaskRegistered; 65 | break; 66 | } 67 | 68 | string status = registered ? "Registered" : "Unregistered"; 69 | 70 | ApplicationDataContainer settings = ApplicationData.Current.LocalSettings; 71 | if (settings.Values.ContainsKey(name)) 72 | { 73 | status += " - " + settings.Values[name]; 74 | } 75 | 76 | return status; 77 | } 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /WinMasto/Brushes/HostBlurBrush.cs: -------------------------------------------------------------------------------- 1 | using Windows.UI.Xaml.Media; 2 | using Microsoft.Graphics.Canvas.Effects; 3 | using Windows.UI.Composition; 4 | using Windows.UI.Xaml; 5 | using Windows.UI; 6 | 7 | // From https://github.com/chungweileong94/NeonUI/blob/master/NeonUI/Brushes/HostBlurBrush.cs 8 | 9 | namespace WinMasto.Brushes 10 | { 11 | public class HostBlurBrush : XamlCompositionBrushBase 12 | { 13 | public Color BlurColor 14 | { 15 | get { return (Color)GetValue(BlurColorProperty); } 16 | set { SetValue(BlurColorProperty, value); } 17 | } 18 | 19 | // Using a DependencyProperty as the backing store for BlurColor. This enables animation, styling, binding, etc... 20 | public static readonly DependencyProperty BlurColorProperty = 21 | DependencyProperty.Register("BlurColor", typeof(Color), typeof(HostBlurBrush), new PropertyMetadata(Color.FromArgb(255, 30, 30, 30), OnBlurColorPropertyChanged)); 22 | 23 | private static void OnBlurColorPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) 24 | { 25 | ((HostBlurBrush)d).OnBlurColorPropertyChanged((Color)e.NewValue); 26 | } 27 | 28 | private void OnBlurColorPropertyChanged(Color newValue) 29 | { 30 | setupBlurEffect(); 31 | } 32 | 33 | public int BlurAmount 34 | { 35 | get { return (int)GetValue(BlurAmountProperty); } 36 | set { SetValue(BlurAmountProperty, value); } 37 | } 38 | 39 | // Using a DependencyProperty as the backing store for BlurAmount. This enables animation, styling, binding, etc... 40 | public static readonly DependencyProperty BlurAmountProperty = 41 | DependencyProperty.Register("BlurAmount", typeof(int), typeof(HostBlurBrush), new PropertyMetadata(30)); 42 | 43 | protected override void OnConnected() 44 | { 45 | setupBlurEffect(); 46 | } 47 | 48 | private void setupBlurEffect() 49 | { 50 | Compositor compositor = Window.Current.Compositor; 51 | 52 | GaussianBlurEffect blurEffect = new GaussianBlurEffect() 53 | { 54 | BlurAmount = BlurAmount, 55 | BorderMode = EffectBorderMode.Hard, 56 | Optimization = EffectOptimization.Balanced, 57 | Source = new ArithmeticCompositeEffect() 58 | { 59 | MultiplyAmount = 0, 60 | Source1Amount = .4f, 61 | Source2Amount = .6f, 62 | Source1 = new CompositionEffectSourceParameter("backdrop"), 63 | Source2 = new ColorSourceEffect() 64 | { 65 | Color = BlurColor 66 | } 67 | } 68 | }; 69 | 70 | var backdropBrush = compositor.CreateHostBackdropBrush(); 71 | 72 | CompositionEffectFactory effectFacotory = compositor.CreateEffectFactory(blurEffect); 73 | var blurBrush = effectFacotory.CreateBrush(); 74 | blurBrush.SetSourceParameter("backdrop", backdropBrush); 75 | 76 | CompositionBrush = blurBrush; 77 | } 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /WinMasto/Views/Shell.xaml.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.IO; 4 | using System.Linq; 5 | using System.Runtime.InteropServices.WindowsRuntime; 6 | using Windows.ApplicationModel; 7 | using Windows.ApplicationModel.Core; 8 | using Windows.Foundation; 9 | using Windows.Foundation.Collections; 10 | using Windows.Foundation.Metadata; 11 | using Windows.UI; 12 | using Windows.UI.Xaml; 13 | using Windows.UI.Xaml.Controls; 14 | using Windows.UI.Xaml.Controls.Primitives; 15 | using Windows.UI.Xaml.Data; 16 | using Windows.UI.Xaml.Input; 17 | using Windows.UI.Xaml.Media; 18 | using Windows.UI.Xaml.Navigation; 19 | using Template10.Controls; 20 | using Template10.Services.NavigationService; 21 | using WinMasto.ViewModels; 22 | 23 | // The Blank Page item template is documented at https://go.microsoft.com/fwlink/?LinkId=234238 24 | 25 | namespace WinMasto.Views 26 | { 27 | /// 28 | /// An empty page that can be used on its own or navigated to within a Frame. 29 | /// 30 | public sealed partial class Shell : Page 31 | { 32 | public static Shell Instance { get; set; } 33 | public static HamburgerMenu HamburgerMenu => Instance.MyHamburgerMenu; 34 | Services.SettingsService _settings; 35 | public ShellViewModel ViewModel => this.DataContext as ShellViewModel; 36 | 37 | public Shell() 38 | { 39 | Instance = this; 40 | InitializeComponent(); 41 | InitilizeTitleBar(); 42 | _settings = Services.SettingsService.Instance; 43 | ViewModel.CheckLogin(); 44 | } 45 | 46 | public Shell(INavigationService navigationService) : this() 47 | { 48 | SetNavigationService(navigationService); 49 | } 50 | 51 | public void SetNavigationService(INavigationService navigationService) 52 | { 53 | MyHamburgerMenu.NavigationService = navigationService; 54 | HamburgerMenu.RefreshStyles(_settings.AppTheme, true); 55 | //HamburgerMenu.IsFullScreen = _settings.IsFullScreen; 56 | //HamburgerMenu.HamburgerButtonVisibility = _settings.ShowHamburgerButton ? Visibility.Visible : Visibility.Collapsed; 57 | } 58 | 59 | private void InitilizeTitleBar() 60 | { 61 | var titleBar = CoreApplication.GetCurrentView().TitleBar; 62 | titleBar.ExtendViewIntoTitleBar = true; 63 | 64 | titleBar.LayoutMetricsChanged += (s, e) => 65 | { 66 | TitleBarGrid.Height = s.Height; 67 | TitleBarContentGrid.Margin = new Thickness(s.SystemOverlayLeftInset + 12, 0, s.SystemOverlayRightInset - 12, 0); 68 | }; 69 | 70 | var view = Windows.UI.ViewManagement.ApplicationView.GetForCurrentView(); 71 | TitleBarTextBlock.Text = Package.Current.DisplayName; 72 | view.TitleBar.BackgroundColor = Colors.Transparent; 73 | view.TitleBar.InactiveBackgroundColor = Colors.Transparent; 74 | view.TitleBar.ButtonBackgroundColor = Colors.Transparent; 75 | view.TitleBar.ButtonInactiveBackgroundColor = Colors.Transparent; 76 | if (ApiInformation.IsTypePresent("Windows.UI.ViewManagement.StatusBar")) 77 | { 78 | TitleBarGrid.Height = 0; 79 | } 80 | } 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /WinMasto/ViewModels/StatusPageViewModel.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Collections.ObjectModel; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | using Windows.UI.Xaml.Navigation; 8 | using Mastonet.Entities; 9 | 10 | namespace WinMasto.ViewModels 11 | { 12 | public class StatusPageViewModel : StatusBaseViewModel 13 | { 14 | public override async Task OnNavigatedToAsync(object parameter, NavigationMode mode, 15 | IDictionary suspensionState) 16 | { 17 | IsLoading = true; 18 | await LoginUser(); 19 | var status = parameter as Status; 20 | if (status == null) 21 | { 22 | IsLoading = false; 23 | return; 24 | } 25 | SelectedStatus = status.Reblog ?? status; 26 | Others = new ObservableCollection(); 27 | Title = status.Account.AccountName; 28 | Card = await Client.GetStatusCard(status.Id); 29 | HasCard = Card.Title != null; 30 | var context = await Client.GetStatusContext(status.Id); 31 | foreach (var item in context.Ancestors.Reverse()) 32 | { 33 | Others.Insert(0, item); 34 | } 35 | foreach (var item in context.Descendants) 36 | { 37 | Others.Add(item); 38 | } 39 | IsLoading = false; 40 | } 41 | 42 | private bool _hasCard; 43 | 44 | public bool HasCard 45 | { 46 | get { return _hasCard; } 47 | set 48 | { 49 | Set(ref _hasCard, value); 50 | } 51 | } 52 | 53 | private Card _card; 54 | 55 | public Card Card 56 | { 57 | get { return _card; } 58 | set 59 | { 60 | Set(ref _card, value); 61 | } 62 | } 63 | 64 | private ObservableCollection _others; 65 | 66 | public ObservableCollection Others 67 | { 68 | get { return _others; } 69 | set 70 | { 71 | Set(ref _others, value); 72 | } 73 | } 74 | 75 | private Status _selectedStatus; 76 | 77 | public Status SelectedStatus 78 | { 79 | get { return _selectedStatus; } 80 | set 81 | { 82 | Set(ref _selectedStatus, value); 83 | } 84 | } 85 | 86 | public async Task ShowNSFWPost(Status status) 87 | { 88 | bool isSelectedStatus = this.SelectedStatus == status; 89 | 90 | Status newStatus = status; 91 | newStatus.Sensitive = false; 92 | newStatus.SpoilerText = string.Empty; 93 | if (Others != null) 94 | { 95 | var index = Others.IndexOf(status); 96 | if (index >= 0) 97 | { 98 | Others[index] = newStatus; 99 | } 100 | } 101 | 102 | if (isSelectedStatus) 103 | { 104 | this.SelectedStatus = newStatus; 105 | } 106 | } 107 | } 108 | } 109 | -------------------------------------------------------------------------------- /WinMasto/Tools/Converters/SpoilerOrNSFWConverter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using Windows.UI.Xaml; 7 | using Windows.UI.Xaml.Data; 8 | using Mastonet.Entities; 9 | 10 | namespace WinMasto.Tools.Converters 11 | { 12 | public class SpoilerOrNSFWVisibilityConverter : IValueConverter 13 | { 14 | public object Convert(object value, Type targetType, object parameter, string language) 15 | { 16 | if (Services.SettingsService.Instance.AlwaysShowNSFW) return Visibility.Collapsed; 17 | var status = value as Status; 18 | if (status == null) return Visibility.Collapsed; 19 | return (status.Sensitive != null && status.Sensitive.Value) || !string.IsNullOrEmpty(status.SpoilerText) ? Visibility.Visible : Visibility.Collapsed; 20 | } 21 | 22 | public object ConvertBack(object value, Type targetType, object parameter, string language) 23 | { 24 | throw new NotImplementedException(); 25 | } 26 | } 27 | 28 | public class SpoilerOrNSFWTextConverter : IValueConverter 29 | { 30 | public object Convert(object value, Type targetType, object parameter, string language) 31 | { 32 | var status = value as Status; 33 | if (status == null) return string.Empty; 34 | return !string.IsNullOrEmpty(status.SpoilerText) ? status.SpoilerText : "NSFW Post"; 35 | } 36 | 37 | public object ConvertBack(object value, Type targetType, object parameter, string language) 38 | { 39 | throw new NotImplementedException(); 40 | } 41 | } 42 | 43 | public class SpoilerOrNSFWConverter : IValueConverter 44 | { 45 | public object Convert(object value, Type targetType, object parameter, string language) 46 | { 47 | var status = value as Status; 48 | if (status == null) return 0; 49 | if (Services.SettingsService.Instance.AlwaysShowNSFW) return 0; 50 | return (status.Sensitive != null && status.Sensitive.Value) || !string.IsNullOrEmpty(status.SpoilerText) ? 20 : 0; 51 | } 52 | 53 | public object ConvertBack(object value, Type targetType, object parameter, string language) 54 | { 55 | throw new NotImplementedException(); 56 | } 57 | } 58 | 59 | public class SpoilerConverter : IValueConverter 60 | { 61 | public object Convert(object value, Type targetType, object parameter, string language) 62 | { 63 | var status = value as Status; 64 | if (status == null) return 0; 65 | return !string.IsNullOrEmpty(status.SpoilerText) ? 4 : 0; 66 | } 67 | 68 | public object ConvertBack(object value, Type targetType, object parameter, string language) 69 | { 70 | throw new NotImplementedException(); 71 | } 72 | } 73 | 74 | public class NSFWConverter : IValueConverter 75 | { 76 | public object Convert(object value, Type targetType, object parameter, string language) 77 | { 78 | var status = value as Status; 79 | if (status == null) return 0; 80 | return (status.Sensitive != null && status.Sensitive.Value) ? 20 : 0; 81 | } 82 | 83 | public object ConvertBack(object value, Type targetType, object parameter, string language) 84 | { 85 | throw new NotImplementedException(); 86 | } 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /WinMasto/Tools/NotificationScrollingCollection.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Collections.ObjectModel; 4 | using System.ComponentModel; 5 | using System.Linq; 6 | using System.Text; 7 | using System.Threading.Tasks; 8 | using Windows.Foundation; 9 | using Windows.UI.Xaml.Data; 10 | using Mastonet; 11 | using Mastonet.Entities; 12 | using Template10.Utils; 13 | 14 | namespace WinMasto.Tools 15 | { 16 | public class NotificationScrollingCollection : ObservableCollection, ISupportIncrementalLoading 17 | { 18 | public NotificationScrollingCollection(MastodonClient client) 19 | { 20 | HasMoreItems = true; 21 | IsLoading = false; 22 | _client = client; 23 | } 24 | 25 | public IAsyncOperation LoadMoreItemsAsync(uint count) 26 | { 27 | return LoadDataAsync(count).AsAsyncOperation(); 28 | } 29 | 30 | public async Task PullToRefresh() 31 | { 32 | var statuses = await RefreshTimeline(true); 33 | if (statuses.Any()) 34 | { 35 | var reverseStatus = statuses.Reverse(); 36 | foreach (var status in reverseStatus) 37 | { 38 | this.Insert(0, status); 39 | } 40 | } 41 | } 42 | 43 | public async Task> RefreshTimeline(bool pullToRefresh) 44 | { 45 | IsLoading = true; 46 | IEnumerable statuses; 47 | try 48 | { 49 | ArrayOptions options = new ArrayOptions(); 50 | if (pullToRefresh) 51 | { 52 | if (this.Any()) 53 | { 54 | options.SinceId = this.First().Id; 55 | } 56 | } 57 | else 58 | { 59 | if (_maxId > 0) 60 | { 61 | options.MaxId = _maxId; 62 | } 63 | } 64 | 65 | statuses = await _client.GetNotifications(options); 66 | } 67 | catch (Exception e) 68 | { 69 | // TODO: Show error 70 | Console.WriteLine(e); 71 | statuses = new List(); 72 | } 73 | IsLoading = false; 74 | return statuses; 75 | } 76 | 77 | public async Task LoadDataAsync(uint count) 78 | { 79 | var statuses = await RefreshTimeline(false); 80 | if (statuses.Any()) 81 | { 82 | this.AddRange(statuses); 83 | _maxId = statuses.Last().Id; 84 | } 85 | else 86 | { 87 | HasMoreItems = false; 88 | } 89 | return new LoadMoreItemsResult { Count = count }; 90 | } 91 | 92 | private bool _isLoading; 93 | public bool IsLoading 94 | { 95 | get { return _isLoading; } 96 | 97 | private set 98 | { 99 | _isLoading = value; 100 | OnPropertyChanged(new PropertyChangedEventArgs("IsLoading")); 101 | } 102 | } 103 | 104 | private int _sinceId; 105 | 106 | private int _maxId; 107 | 108 | private MastodonClient _client; 109 | 110 | public bool HasMoreItems { get; set; } 111 | } 112 | } 113 | -------------------------------------------------------------------------------- /WinMasto/Effects/PointLightEffect.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using Windows.UI; 7 | using Windows.UI.Composition; 8 | using Windows.UI.Xaml; 9 | using Windows.UI.Xaml.Media; 10 | 11 | namespace WinMasto.Effects 12 | { 13 | public class PointLightEffect : XamlLight 14 | { 15 | // Register an attached proeprty that enables apps to set a UIElement or Brush as a target for this light type in markup. 16 | public static readonly DependencyProperty IsTargetProperty = 17 | DependencyProperty.RegisterAttached( 18 | "IsTarget", 19 | typeof(Boolean), 20 | typeof(PointLightEffect), 21 | new PropertyMetadata(null, OnIsTargetChanged) 22 | ); 23 | public static void SetIsTarget(DependencyObject target, Boolean value) 24 | { 25 | target.SetValue(IsTargetProperty, value); 26 | } 27 | public static Boolean GetIsTarget(DependencyObject target) 28 | { 29 | return (Boolean)target.GetValue(IsTargetProperty); 30 | } 31 | 32 | // Handle attached property changed to automatically target and untarget UIElements and Brushes. 33 | private static void OnIsTargetChanged(DependencyObject obj, 34 | DependencyPropertyChangedEventArgs e) 35 | { 36 | var isAdding = (Boolean)e.NewValue; 37 | 38 | if (isAdding) 39 | { 40 | if (obj is UIElement) 41 | { 42 | AddTargetElement(GetIdStatic(), obj as UIElement); 43 | } 44 | else if (obj is Brush) 45 | { 46 | AddTargetBrush(GetIdStatic(), obj as Brush); 47 | } 48 | } 49 | else 50 | { 51 | if (obj is UIElement) 52 | { 53 | RemoveTargetElement(GetIdStatic(), obj as UIElement); 54 | } 55 | else if (obj is Brush) 56 | { 57 | RemoveTargetBrush(GetIdStatic(), obj as Brush); 58 | } 59 | } 60 | } 61 | 62 | protected override void OnConnected(UIElement newElement) 63 | { 64 | // OnConnected is called when the first target UIElement is shown on the screen. This enables delaying composition object creation until it's actually necessary. 65 | CompositionLight = Window.Current.Compositor.CreatePointLight(); 66 | ((PointLight)CompositionLight).Color = Colors.White; 67 | 68 | newElement.PointerMoved += (s, e) => 69 | { 70 | var pos = e.GetCurrentPoint(newElement).Position; 71 | ((PointLight)CompositionLight).Offset = new System.Numerics.Vector3((float)pos.X, (float)pos.Y, 45); 72 | }; 73 | } 74 | 75 | protected override void OnDisconnected(UIElement oldElement) 76 | { 77 | // OnDisconnected is called when there are no more target UIElements on the screen. The CompositionLight should be disposed when no longer required. 78 | CompositionLight.Dispose(); 79 | CompositionLight = null; 80 | } 81 | 82 | protected override string GetId() 83 | { 84 | return GetIdStatic(); 85 | } 86 | 87 | private static string GetIdStatic() 88 | { 89 | // This specifies the unique name of the light. In most cases you should use the type's FullName. 90 | return typeof(PointLightEffect).FullName; 91 | } 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /WinMasto/Views/NewStatusPage.xaml.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.IO; 4 | using System.Linq; 5 | using System.Runtime.InteropServices.WindowsRuntime; 6 | using Windows.Foundation; 7 | using Windows.Foundation.Collections; 8 | using Windows.Storage; 9 | using Windows.Storage.FileProperties; 10 | using Windows.Storage.Pickers; 11 | using Windows.UI.Xaml; 12 | using Windows.UI.Xaml.Controls; 13 | using Windows.UI.Xaml.Controls.Primitives; 14 | using Windows.UI.Xaml.Data; 15 | using Windows.UI.Xaml.Input; 16 | using Windows.UI.Xaml.Media; 17 | using Windows.UI.Xaml.Navigation; 18 | using WinMasto.Models; 19 | using WinMasto.ViewModels; 20 | 21 | // The Blank Page item template is documented at https://go.microsoft.com/fwlink/?LinkId=234238 22 | 23 | namespace WinMasto.Views 24 | { 25 | /// 26 | /// An empty page that can be used on its own or navigated to within a Frame. 27 | /// 28 | public sealed partial class NewStatusPage : Page 29 | { 30 | public NewStatusPage() 31 | { 32 | this.InitializeComponent(); 33 | this.NavigationCacheMode = NavigationCacheMode.Disabled; 34 | VisibilityListBox.SelectedIndex = 0; 35 | } 36 | 37 | public NewStatusPageViewModel ViewModel => this.DataContext as NewStatusPageViewModel; 38 | 39 | private async void SelectPhotos_OnClick(object sender, RoutedEventArgs e) 40 | { 41 | ViewModel.IsLoading = true; 42 | var openPicker = new FileOpenPicker 43 | { 44 | 45 | ViewMode = PickerViewMode.Thumbnail, 46 | SuggestedStartLocation = PickerLocationId.PicturesLibrary 47 | }; 48 | openPicker.FileTypeFilter.Add(".jpg"); 49 | openPicker.FileTypeFilter.Add(".jpeg"); 50 | openPicker.FileTypeFilter.Add(".png"); 51 | openPicker.FileTypeFilter.Add(".gif"); 52 | StorageFile file = await openPicker.PickSingleFileAsync(); 53 | if (file == null) 54 | { 55 | ViewModel.IsLoading = false; 56 | return; 57 | } 58 | var photoFileInfo = new PhotoFileInfo() 59 | { 60 | File = file, 61 | Thumbnail = await file.GetThumbnailAsync(ThumbnailMode.SingleItem) 62 | }; 63 | using (var randomStream = await file.OpenAsync(FileAccessMode.Read)) 64 | { 65 | var attachment = await ViewModel.Client.UploadMedia(randomStream.AsStream(), Path.GetFileName(file.Path)); 66 | try 67 | { 68 | StatusTextBox.Text += $" {attachment.Url}"; 69 | photoFileInfo.Attachment = attachment; 70 | ViewModel.PhotoList.Add(photoFileInfo); 71 | } 72 | catch (Exception exception) 73 | { 74 | Console.WriteLine(exception); 75 | } 76 | ViewModel.IsLoading = false; 77 | } 78 | } 79 | 80 | private void RemovePhoto_OnClick(object sender, RoutedEventArgs e) 81 | { 82 | var menuFlyoutItem = sender as Button; 83 | var status = menuFlyoutItem?.CommandParameter as PhotoFileInfo; 84 | if (status == null) return; 85 | var newText = StatusTextBox.Text.Remove(StatusTextBox.Text.IndexOf(status.Attachment.Url, StringComparison.Ordinal), status.Attachment.Url.Length); 86 | StatusTextBox.Text = newText; 87 | ViewModel.PhotoList.Remove(status); 88 | } 89 | 90 | private void ChangeSpoilerMode_OnClick(object sender, RoutedEventArgs e) 91 | { 92 | ViewModel.Sensitive = !ViewModel.Sensitive; 93 | } 94 | 95 | private void VisibilityChanged_OnClick(object sender, SelectionChangedEventArgs e) 96 | { 97 | ViewModel.StatusVisibility = (Mastonet.Visibility) VisibilityListBox.SelectedIndex; 98 | } 99 | } 100 | } 101 | -------------------------------------------------------------------------------- /WinMasto/Views/LoginPage.xaml: -------------------------------------------------------------------------------- 1 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 114 | 117 | 118 | Public 119 | Unlisted 120 | Private 121 | Direct 122 | 123 | 124 | 125 | 126 | 127 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 81 | 87 | 93 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 118 | 119 | 120 | 121 | 122 | --------------------------------------------------------------------------------