├── .github ├── FUNDING.yml ├── ISSUE_TEMPLATE │ ├── feature_request.md │ ├── generic-bug-report.md │ ├── tizen-6--bug.md │ └── tizen-6-5--bug.md ├── workflows │ ├── close-stale-issues.yml │ └── update-version-table.yml ├── pull_request_template.md ├── SECURITY.md ├── jellyfin-tizen-logo.svg ├── CONTRIBUTING.md └── CODE_OF_CONDUCT.md ├── docs ├── CNAME ├── favicon.ico └── index.html ├── Jellyfin2Samsung-CrossOS ├── Assets │ ├── TizenSDB │ │ └── do-not-remove.txt │ ├── Certificate │ │ └── Jellyfin │ │ │ ├── password.txt │ │ │ ├── author.p12 │ │ │ └── distributor.p12 │ ├── jelly2sams.ico │ ├── jelly2sams.png │ ├── jelly2sams.icns │ └── TizenProfile │ │ └── ca │ │ ├── author_ca.cer │ │ ├── public2.crt │ │ ├── vd_tizen_dev_author_ca.cer │ │ └── vd_tizen_dev_public2.crt ├── Extensions │ ├── ProgressCallback.cs │ └── LocalizationExtensions.cs ├── ViewModels │ ├── ViewModelBase.cs │ ├── InstallingWindowViewModel.cs │ ├── IpInputDialogViewModel.cs │ ├── InstallationCompleteViewModel.cs │ ├── TvLogsViewModel.cs │ └── BuildInfoViewModel.cs ├── Models │ ├── TvLogConnectionStatus.cs │ ├── TvLogMessage.cs │ ├── ProcessResult.cs │ ├── BuildVersion.cs │ ├── DeviceCapabilities.cs │ ├── InstallResult.cs │ ├── JellyfinAuth.cs │ ├── LanguageOption.cs │ ├── SamsungAuth.cs │ ├── ExistingCertificates.cs │ ├── JellyfinPluginInfo.cs │ ├── NetworkDevice.cs │ └── GitHubRelease.cs ├── Views │ ├── SettingsView.axaml.cs │ ├── JellyfinConfigView.axaml.cs │ ├── InstallationCompleteWindow.axaml.cs │ ├── InstallingWindow.axaml.cs │ ├── BuildInfoWindow.axaml.cs │ ├── MainWindow.axaml.cs │ ├── IpInputDialog.axaml.cs │ ├── InstallingWindow.axaml │ ├── TvLogsWindow.axaml.cs │ ├── IpInputDialog.axaml │ ├── InstallationCompleteWindow.axaml │ ├── BuildInfoWindow.axaml │ ├── TvLogsWindow.axaml │ ├── MainWindow.axaml │ └── SettingsView.axaml ├── jellyfin2samsung.desktop ├── Interfaces │ ├── ITizenCertificateService.cs │ ├── ILocalizationService.cs │ ├── IDialogService.cs │ ├── ITizenInstallerService.cs │ └── INetworkService.cs ├── Styles │ ├── TextBlocks.axaml │ ├── ComboBoxes.axaml │ └── Buttons.axaml ├── App.axaml ├── Program.cs ├── ViewLocator.cs ├── app.manifest ├── Info.plist ├── Helpers │ ├── StatusToColorConverter.cs │ ├── CipherUtil.cs │ ├── EsbuildHelper.cs │ ├── DeviceHelper.cs │ ├── ProcessHelper.cs │ ├── CertificateHelper.cs │ ├── AppSettings.cs │ ├── PackageHelper.cs │ ├── FileHelper.cs │ └── JellyfinApiClient.cs ├── Services │ ├── LocalizationService.cs │ ├── TvLogService.cs │ ├── SamsungLoginService.cs │ └── DialogService.cs ├── Jellyfin2Samsung.csproj ├── App.axaml.cs └── build.ps1 ├── jellyfin.ico ├── LICENSE ├── Jellyfin2Samsung-CrossOS.sln ├── jellyfin-tizen-logo.svg ├── .gitattributes └── .gitignore /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | ko_fi: patrickst 2 | -------------------------------------------------------------------------------- /docs/CNAME: -------------------------------------------------------------------------------- 1 | jellyfin2samsung.madebypatrick.nl -------------------------------------------------------------------------------- /Jellyfin2Samsung-CrossOS/Assets/TizenSDB/do-not-remove.txt: -------------------------------------------------------------------------------- 1 | placeholder -------------------------------------------------------------------------------- /Jellyfin2Samsung-CrossOS/Assets/Certificate/Jellyfin/password.txt: -------------------------------------------------------------------------------- 1 | tizenpkcs12passfordsigner -------------------------------------------------------------------------------- /jellyfin.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PatrickSt1991/Samsung-Jellyfin-Installer/HEAD/jellyfin.ico -------------------------------------------------------------------------------- /docs/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PatrickSt1991/Samsung-Jellyfin-Installer/HEAD/docs/favicon.ico -------------------------------------------------------------------------------- /Jellyfin2Samsung-CrossOS/Assets/jelly2sams.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PatrickSt1991/Samsung-Jellyfin-Installer/HEAD/Jellyfin2Samsung-CrossOS/Assets/jelly2sams.ico -------------------------------------------------------------------------------- /Jellyfin2Samsung-CrossOS/Assets/jelly2sams.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PatrickSt1991/Samsung-Jellyfin-Installer/HEAD/Jellyfin2Samsung-CrossOS/Assets/jelly2sams.png -------------------------------------------------------------------------------- /Jellyfin2Samsung-CrossOS/Assets/jelly2sams.icns: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PatrickSt1991/Samsung-Jellyfin-Installer/HEAD/Jellyfin2Samsung-CrossOS/Assets/jelly2sams.icns -------------------------------------------------------------------------------- /Jellyfin2Samsung-CrossOS/Extensions/ProgressCallback.cs: -------------------------------------------------------------------------------- 1 | namespace Jellyfin2Samsung.Extensions 2 | { 3 | public delegate void ProgressCallback(string message); 4 | } 5 | -------------------------------------------------------------------------------- /Jellyfin2Samsung-CrossOS/Assets/Certificate/Jellyfin/author.p12: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PatrickSt1991/Samsung-Jellyfin-Installer/HEAD/Jellyfin2Samsung-CrossOS/Assets/Certificate/Jellyfin/author.p12 -------------------------------------------------------------------------------- /Jellyfin2Samsung-CrossOS/Assets/Certificate/Jellyfin/distributor.p12: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PatrickSt1991/Samsung-Jellyfin-Installer/HEAD/Jellyfin2Samsung-CrossOS/Assets/Certificate/Jellyfin/distributor.p12 -------------------------------------------------------------------------------- /Jellyfin2Samsung-CrossOS/ViewModels/ViewModelBase.cs: -------------------------------------------------------------------------------- 1 | using CommunityToolkit.Mvvm.ComponentModel; 2 | 3 | namespace Jellyfin2Samsung.ViewModels 4 | { 5 | public class ViewModelBase : ObservableObject 6 | { 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /Jellyfin2Samsung-CrossOS/Models/TvLogConnectionStatus.cs: -------------------------------------------------------------------------------- 1 | namespace Jellyfin2Samsung.Models 2 | { 3 | public enum TvLogConnectionStatus 4 | { 5 | Stopped, 6 | Listening, 7 | Connected, 8 | NoConnections 9 | } 10 | } -------------------------------------------------------------------------------- /Jellyfin2Samsung-CrossOS/Models/TvLogMessage.cs: -------------------------------------------------------------------------------- 1 | 2 | namespace Jellyfin2Samsung.Models 3 | { 4 | public class TvLogMessage 5 | { 6 | public string level { get; set; } 7 | public object msg { get; set; } 8 | public object meta { get; set; } 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /Jellyfin2Samsung-CrossOS/Views/SettingsView.axaml.cs: -------------------------------------------------------------------------------- 1 | using Avalonia; 2 | using Avalonia.Controls; 3 | using Avalonia.Markup.Xaml; 4 | 5 | namespace Jellyfin2Samsung; 6 | 7 | public partial class SettingsView : Window 8 | { 9 | public SettingsView() 10 | { 11 | InitializeComponent(); 12 | } 13 | } -------------------------------------------------------------------------------- /Jellyfin2Samsung-CrossOS/Models/ProcessResult.cs: -------------------------------------------------------------------------------- 1 | namespace Jellyfin2Samsung.Models 2 | { 3 | public class ProcessResult 4 | { 5 | public int ExitCode { get; set; } 6 | public string Output { get; set; } = string.Empty; 7 | public string Error { get; set; } = string.Empty; 8 | } 9 | 10 | } 11 | -------------------------------------------------------------------------------- /Jellyfin2Samsung-CrossOS/jellyfin2samsung.desktop: -------------------------------------------------------------------------------- 1 | [Desktop Entry] 2 | Version=1.0 3 | Type=Application 4 | Name=Jellyfin2Samsung 5 | Comment=Install Jellyfin on Samsung Smart TVs 6 | Icon=jelly2sams 7 | Terminal=false 8 | Categories=Utility;Network; 9 | StartupNotify=true 10 | MimeType=application/x-jellyfin2samsung; 11 | Exec=start-jellyfin2samsung.sh 12 | -------------------------------------------------------------------------------- /Jellyfin2Samsung-CrossOS/Views/JellyfinConfigView.axaml.cs: -------------------------------------------------------------------------------- 1 | using Avalonia.Controls; 2 | using Jellyfin2Samsung.ViewModels; 3 | 4 | namespace Jellyfin2Samsung; 5 | 6 | public partial class JellyfinConfigView : Window 7 | { 8 | public JellyfinConfigView(JellyfinConfigViewModel vm) 9 | { 10 | InitializeComponent(); 11 | DataContext = vm; 12 | } 13 | } -------------------------------------------------------------------------------- /Jellyfin2Samsung-CrossOS/Models/BuildVersion.cs: -------------------------------------------------------------------------------- 1 | using CommunityToolkit.Mvvm.ComponentModel; 2 | 3 | namespace Jellyfin2Samsung.Models 4 | { 5 | public partial class BuildVersion : ObservableObject 6 | { 7 | [ObservableProperty] private string fileName = string.Empty; 8 | [ObservableProperty] private string description = string.Empty; 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /Jellyfin2Samsung-CrossOS/Views/InstallationCompleteWindow.axaml.cs: -------------------------------------------------------------------------------- 1 | using Avalonia.Controls; 2 | using Jellyfin2Samsung.ViewModels; 3 | 4 | namespace Jellyfin2Samsung; 5 | 6 | public partial class InstallationCompleteWindow : Window 7 | { 8 | public InstallationCompleteWindow(InstallationCompleteViewModel vm) 9 | { 10 | InitializeComponent(); 11 | DataContext = vm; 12 | } 13 | } -------------------------------------------------------------------------------- /Jellyfin2Samsung-CrossOS/Models/DeviceCapabilities.cs: -------------------------------------------------------------------------------- 1 | namespace Jellyfin2Samsung.Models 2 | { 3 | internal class DeviceCapabilities 4 | { 5 | public bool SupportsDeveloperMode { get; set; } 6 | public string ApiVersion { get; set; } = string.Empty; 7 | public string TizenVersion { get; set; } = string.Empty; 8 | public int ModelYear { get; set; } 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /Jellyfin2Samsung-CrossOS/Interfaces/ITizenCertificateService.cs: -------------------------------------------------------------------------------- 1 | using Jellyfin2Samsung.Extensions; 2 | using System.Threading.Tasks; 3 | 4 | namespace Jellyfin2Samsung.Interfaces 5 | { 6 | public interface ITizenCertificateService 7 | { 8 | Task<(string authorP12, string distributorP12, string passwordP12)> GenerateProfileAsync(string duid, string accessToken, string userId, string userEmail, string outputPath, ProgressCallback? progress = null); 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /Jellyfin2Samsung-CrossOS/Views/InstallingWindow.axaml.cs: -------------------------------------------------------------------------------- 1 | using Avalonia.Controls; 2 | using Jellyfin2Samsung.ViewModels; 3 | 4 | namespace Jellyfin2Samsung; 5 | 6 | public partial class InstallingWindow : Window 7 | { 8 | public InstallingWindowViewModel ViewModel { get; } 9 | 10 | public InstallingWindow() 11 | { 12 | InitializeComponent(); 13 | 14 | ViewModel = new InstallingWindowViewModel(); 15 | DataContext = ViewModel; 16 | } 17 | } -------------------------------------------------------------------------------- /Jellyfin2Samsung-CrossOS/Interfaces/ILocalizationService.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace Jellyfin2Samsung.Interfaces 5 | { 6 | public interface ILocalizationService 7 | { 8 | string GetString(string key); 9 | void SetLanguage(string languageCode); 10 | string CurrentLanguage { get; } 11 | IEnumerable AvailableLanguages { get; } 12 | event EventHandler? LanguageChanged; 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /Jellyfin2Samsung-CrossOS/Views/BuildInfoWindow.axaml.cs: -------------------------------------------------------------------------------- 1 | using Avalonia.Controls; 2 | using Jellyfin2Samsung.ViewModels; 3 | 4 | namespace Jellyfin2Samsung.Views 5 | { 6 | public partial class BuildInfoWindow : Window 7 | { 8 | private readonly BuildInfoViewModel _vm = new(); 9 | 10 | public BuildInfoWindow() 11 | { 12 | InitializeComponent(); 13 | DataContext = _vm; 14 | _vm.OnRequestClose += Close; 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /Jellyfin2Samsung-CrossOS/Interfaces/IDialogService.cs: -------------------------------------------------------------------------------- 1 | using Avalonia.Controls; 2 | using System.Threading.Tasks; 3 | 4 | namespace Jellyfin2Samsung.Interfaces 5 | { 6 | public interface IDialogService 7 | { 8 | Task ShowMessageAsync(string title, string message); 9 | Task ShowErrorAsync(string message); 10 | Task ShowConfirmationAsync(string title, string message, string yes, string no, Window? owner = null); 11 | Task PromptForIpAsync(); 12 | 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /Jellyfin2Samsung-CrossOS/Models/InstallResult.cs: -------------------------------------------------------------------------------- 1 | namespace Jellyfin2Samsung.Models 2 | { 3 | public class InstallResult 4 | { 5 | public bool Success { get; init; } 6 | public string ErrorMessage { get; init; } 7 | 8 | public static InstallResult SuccessResult() => new() { Success = true }; 9 | public static InstallResult FailureResult(string error) => new() 10 | { 11 | Success = false, 12 | ErrorMessage = error 13 | }; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /Jellyfin2Samsung-CrossOS/Styles/TextBlocks.axaml: -------------------------------------------------------------------------------- 1 | 3 | 8 | 9 | 13 | 14 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature Request 3 | about: Suggest a new feature or improvement for the application 4 | title: "[Feature] " 5 | labels: enhancement, keep-alive 6 | assignees: PatrickSt1991 7 | --- 8 | 9 | **Feature Description** 10 | Please describe the feature you'd like to see. 11 | 12 | **Why Is This Feature Useful?** 13 | Explain why this feature is beneficial or how it improves the app. 14 | 15 | **Additional Context** 16 | Add any other context, screenshots, or mockups that help explain your request. 17 | -------------------------------------------------------------------------------- /Jellyfin2Samsung-CrossOS/Views/MainWindow.axaml.cs: -------------------------------------------------------------------------------- 1 | using Avalonia.Controls; 2 | using Jellyfin2Samsung.ViewModels; 3 | 4 | namespace Jellyfin2Samsung.Views 5 | { 6 | public partial class MainWindow : Window 7 | { 8 | public MainWindow() 9 | { 10 | InitializeComponent(); 11 | this.Opened += async (_, __) => 12 | { 13 | if (DataContext is MainWindowViewModel vm) 14 | { 15 | await vm.InitializeAsync(); 16 | } 17 | }; 18 | } 19 | } 20 | } -------------------------------------------------------------------------------- /Jellyfin2Samsung-CrossOS/Styles/ComboBoxes.axaml: -------------------------------------------------------------------------------- 1 | 3 | 12 | 13 | -------------------------------------------------------------------------------- /Jellyfin2Samsung-CrossOS/Interfaces/ITizenInstallerService.cs: -------------------------------------------------------------------------------- 1 | using Jellyfin2Samsung.Extensions; 2 | using Jellyfin2Samsung.Models; 3 | using System.Threading.Tasks; 4 | 5 | namespace Jellyfin2Samsung.Interfaces 6 | { 7 | public interface ITizenInstallerService 8 | { 9 | Task GetTvNameAsync(string tvIpAddress); 10 | Task EnsureTizenSdbAvailable(); 11 | Task DownloadPackageAsync(string downloadUrl); 12 | Task InstallPackageAsync(string packageUrl, string tvIpAddress, ProgressCallback? progress = null); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /Jellyfin2Samsung-CrossOS/ViewModels/InstallingWindowViewModel.cs: -------------------------------------------------------------------------------- 1 | using CommunityToolkit.Mvvm.ComponentModel; 2 | 3 | namespace Jellyfin2Samsung.ViewModels 4 | { 5 | public partial class InstallingWindowViewModel : ObservableObject 6 | { 7 | private string _statusText = "Installing Tizen CLI..."; 8 | 9 | public string StatusText 10 | { 11 | get => _statusText; 12 | set => SetProperty(ref _statusText, value); 13 | } 14 | public void SetStatusText(string text) 15 | { 16 | StatusText = text; 17 | } 18 | 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /Jellyfin2Samsung-CrossOS/Extensions/LocalizationExtensions.cs: -------------------------------------------------------------------------------- 1 | using Jellyfin2Samsung.Interfaces; 2 | 3 | namespace Jellyfin2Samsung.Extensions 4 | { 5 | public static class LocalizationExtensions 6 | { 7 | private static ILocalizationService? _localizationService; 8 | 9 | public static void SetLocalizationService(ILocalizationService service) 10 | { 11 | _localizationService = service; 12 | } 13 | 14 | public static string Localized(this string key) 15 | { 16 | return _localizationService?.GetString(key) ?? key; 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /Jellyfin2Samsung-CrossOS/Models/JellyfinAuth.cs: -------------------------------------------------------------------------------- 1 | namespace Jellyfin2Samsung.Models 2 | { 3 | public class JellyfinAuth 4 | { 5 | public string Id { get; set; } 6 | public string Name { get; set; } 7 | } 8 | public class JellyfinPublicSystemInfo 9 | { 10 | public string? LocalAddress { get; set; } 11 | public string? ServerName { get; set; } 12 | public string? Version { get; set; } 13 | public string? ProductName { get; set; } 14 | public string? OperatingSystem { get; set; } 15 | public string? Id { get; set; } 16 | public bool StartupWizardCompleted { get; set; } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /Jellyfin2Samsung-CrossOS/Models/LanguageOption.cs: -------------------------------------------------------------------------------- 1 | namespace Jellyfin2Samsung.Models 2 | { 3 | public class LanguageOption 4 | { 5 | public string Code { get; set; } 6 | public string Name { get; set; } 7 | 8 | public override string ToString() => Name; 9 | 10 | public override bool Equals(object obj) 11 | { 12 | if (obj is LanguageOption other) 13 | { 14 | return Code == other.Code; 15 | } 16 | return false; 17 | } 18 | 19 | public override int GetHashCode() 20 | { 21 | return Code?.GetHashCode() ?? 0; 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /.github/workflows/close-stale-issues.yml: -------------------------------------------------------------------------------- 1 | name: Close stale issues 2 | 3 | on: 4 | schedule: 5 | - cron: '0 0 * * *' # runs daily at midnight UTC 6 | workflow_dispatch: # allows manual triggering 7 | 8 | permissions: 9 | issues: write 10 | pull-requests: write 11 | 12 | jobs: 13 | stale: 14 | runs-on: ubuntu-latest 15 | steps: 16 | - uses: actions/stale@v9 17 | with: 18 | stale-issue-message: 'This issue has been automatically marked as stale due to inactivity. It will be closed in 24 hours if no further activity occurs.' 19 | stale-issue-label: 'stale' 20 | days-before-stale: 4 21 | days-before-close: 1 22 | exempt-issue-labels: 'keep-alive' -------------------------------------------------------------------------------- /Jellyfin2Samsung-CrossOS/App.axaml: -------------------------------------------------------------------------------- 1 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 17 | 18 | -------------------------------------------------------------------------------- /Jellyfin2Samsung-CrossOS/Models/SamsungAuth.cs: -------------------------------------------------------------------------------- 1 | namespace Jellyfin2Samsung.Models 2 | { 3 | public class SamsungAuth 4 | { 5 | public string access_token { get; set; } 6 | public string token_type { get; set; } 7 | public string access_token_expires_in { get; set; } 8 | public string refresh_token { get; set; } 9 | public string refresh_token_expires_in { get; set; } 10 | public string userId { get; set; } 11 | public string client_id { get; set; } 12 | public string inputEmailID { get; set; } 13 | public string api_server_url { get; set; } 14 | public string auth_server_url { get; set; } 15 | public bool close { get; set; } 16 | public string closedAction { get; set; } 17 | public string state { get; set; } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/generic-bug-report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Generic bug report 3 | about: Create a report to help us improve 4 | title: "[Bug] " 5 | labels: bug, keep-alive 6 | assignees: PatrickSt1991 7 | --- 8 | 9 | **Have you checked the wiki?** 10 | [Samsung Jellyfin Installer Wiki](https://github.com/PatrickSt1991/Samsung-Jellyfin-Installer/wiki/FAQ) 11 | 12 | **Have you included the log files in this issue?** 13 | - Yes 14 | - No 15 | 16 | **Which version of the application did you use?** 17 | (e.g., v1.2.3.4) 18 | 19 | **Is your Samsung TV in developer mode?** 20 | - Yes 21 | - No 22 | 23 | **What Tizen version is your TV running?** 24 | (e.g., Tizen 5.0, 6.5, etc.) 25 | 26 | **Operating system?** 27 | - Windows 28 | - Linux 29 | - macOS 30 | 31 | **Additional Context** 32 | Add any other context or logs about the problem here. 33 | -------------------------------------------------------------------------------- /Jellyfin2Samsung-CrossOS/Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Avalonia; 3 | 4 | namespace Jellyfin2Samsung 5 | { 6 | internal sealed class Program 7 | { 8 | // Initialization code. Don't use any Avalonia, third-party APIs or any 9 | // SynchronizationContext-reliant code before AppMain is called: things aren't initialized 10 | // yet and stuff might break. 11 | [STAThread] 12 | public static void Main(string[] args) => BuildAvaloniaApp() 13 | .StartWithClassicDesktopLifetime(args); 14 | 15 | // Avalonia configuration, don't remove; also used by visual designer. 16 | public static AppBuilder BuildAvaloniaApp() 17 | => AppBuilder.Configure() 18 | .UsePlatformDetect() 19 | .WithInterFont() 20 | .LogToTrace(); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/tizen-6--bug.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Tizen 7- Bug 3 | about: Create a report to help us improve 4 | title: "[Tizen 7-] [Bug] " 5 | labels: bug, keep-alive, tizen 7- 6 | assignees: PatrickSt1991 7 | 8 | --- 9 | 10 | **Have you checked the wiki?** 11 | [Samsung Jellyfin Installer Wiki](https://github.com/PatrickSt1991/Samsung-Jellyfin-Installer/wiki/FAQ) 12 | 13 | **Have you included the log files in this issue?** 14 | - Yes 15 | - No 16 | 17 | **Which version of the application did you use?** 18 | (e.g., v1.2.3.4) 19 | 20 | **Is your Samsung TV in developer mode?** 21 | - Yes 22 | - No 23 | 24 | **What Tizen version is your TV running?** 25 | (e.g., Tizen 5.0, 6.5, etc.) 26 | 27 | **Operating system?** 28 | - Windows 29 | - Linux 30 | - macOS 31 | 32 | **Additional Context** 33 | Add any other context or logs about the problem here. 34 | -------------------------------------------------------------------------------- /Jellyfin2Samsung-CrossOS/Models/ExistingCertificates.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Globalization; 3 | 4 | namespace Jellyfin2Samsung.Models 5 | { 6 | public class ExistingCertificates 7 | { 8 | public required string Name { get; set; } 9 | public required string Duid { get; set; } 10 | public string? File { get; set; } 11 | public string? Location { get; set; } 12 | public DateTime? ExpireDate { get; set; } 13 | public bool? Expired => ExpireDate.HasValue ? ExpireDate.Value < DateTime.Now : null; 14 | public string? Status { get; set; } 15 | public string DisplayText => 16 | $"{Name}" + ( 17 | Status != null ? $" ({Status})" : 18 | ExpireDate.HasValue ? $" ({ExpireDate.Value.ToString("D", CultureInfo.CurrentCulture)})" : "" 19 | ); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/tizen-6-5--bug.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Tizen 7+ Bug 3 | about: Create a report to help us improve the application 4 | title: "[Tizen 7+] [Bug] " 5 | labels: bug, keep-alive, tizen 7+ 6 | assignees: PatrickSt1991 7 | 8 | --- 9 | 10 | **Have you checked the wiki?** 11 | [Samsung Jellyfin Installer Wiki](https://github.com/PatrickSt1991/Samsung-Jellyfin-Installer/wiki/FAQ) 12 | 13 | **Have you included the log files in this issue?** 14 | - Yes 15 | - No 16 | 17 | **Which version of the application did you use?** 18 | (e.g., v1.2.3.4) 19 | 20 | **Is your Samsung TV in developer mode?** 21 | - Yes 22 | - No 23 | 24 | **What Tizen version is your TV running?** 25 | (e.g., Tizen 5.0, 6.5, etc.) 26 | 27 | **Operating system?** 28 | - Windows 29 | - Linux 30 | - macOS 31 | 32 | **Additional Context** 33 | Add any other context or logs about the problem here. 34 | -------------------------------------------------------------------------------- /Jellyfin2Samsung-CrossOS/Views/IpInputDialog.axaml.cs: -------------------------------------------------------------------------------- 1 | using Avalonia.Controls; 2 | using Jellyfin2Samsung; 3 | using Jellyfin2Samsung.Interfaces; 4 | using Jellyfin2Samsung.ViewModels; 5 | using Microsoft.Extensions.DependencyInjection; 6 | using System.Threading.Tasks; 7 | 8 | namespace Jellyfin2Samsung; 9 | 10 | public partial class IpInputDialog : Window 11 | { 12 | public IpInputDialogViewModel ViewModel { get; } 13 | 14 | public IpInputDialog() 15 | { 16 | InitializeComponent(); 17 | 18 | var loc = App.Services.GetRequiredService(); 19 | 20 | ViewModel = new IpInputDialogViewModel(loc, confirmed => Close()); 21 | DataContext = ViewModel; 22 | } 23 | 24 | public async Task ShowDialogAsync(Window parent) 25 | { 26 | await ShowDialog(parent); 27 | return ViewModel.EnteredIp; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /Jellyfin2Samsung-CrossOS/ViewLocator.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Avalonia.Controls; 3 | using Avalonia.Controls.Templates; 4 | using Jellyfin2Samsung.ViewModels; 5 | 6 | namespace Jellyfin2Samsung 7 | { 8 | public class ViewLocator : IDataTemplate 9 | { 10 | 11 | public Control? Build(object? param) 12 | { 13 | if (param is null) 14 | return null; 15 | 16 | var name = param.GetType().FullName!.Replace("ViewModel", "View", StringComparison.Ordinal); 17 | var type = Type.GetType(name); 18 | 19 | if (type != null) 20 | { 21 | return (Control)Activator.CreateInstance(type)!; 22 | } 23 | 24 | return new TextBlock { Text = "Not Found: " + name }; 25 | } 26 | 27 | public bool Match(object? data) 28 | { 29 | return data is ViewModelBase; 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /Jellyfin2Samsung-CrossOS/Interfaces/INetworkService.cs: -------------------------------------------------------------------------------- 1 | using Jellyfin2Samsung.Models; 2 | using System.Collections.Generic; 3 | using System.Net; 4 | using System.Threading; 5 | using System.Threading.Tasks; 6 | 7 | namespace Jellyfin2Samsung.Interfaces 8 | { 9 | public interface INetworkService 10 | { 11 | Task> GetLocalTizenAddresses(CancellationToken cancellationToken = default, bool virtualScan = false); 12 | Task ValidateManualTizenAddress(string ip, CancellationToken cancellationToken = default); 13 | IEnumerable GetRelevantLocalIPs(bool virtualScan = false); 14 | Task IsPortOpenAsync(string ip, int port, CancellationToken ct); 15 | string GetLocalIPAddress(); 16 | string InvertIPAddress(string ipAddress); 17 | Task GetManufacturerFromIp(string ipAddress); 18 | Task GetPrimaryOutboundIPAddressAsync(); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /.github/pull_request_template.md: -------------------------------------------------------------------------------- 1 | # Pull Request Template 2 | 3 | ## Description 4 | 5 | Please include a summary of the change and which issue is fixed. Also include relevant motivation and context. 6 | 7 | Fixes # (issue number, if applicable) 8 | 9 | --- 10 | 11 | ## Type of Change 12 | 13 | - [ ] Bug fix (non-breaking change) 14 | - [ ] New feature (non-breaking change) 15 | - [ ] Breaking change (fix or feature that would cause existing functionality to change) 16 | - [ ] Documentation update 17 | - [ ] Other (please describe): 18 | 19 | --- 20 | 21 | ## Checklist 22 | 23 | - [ ] My code follows the existing project structure and style 24 | - [ ] I have tested my changes manually 25 | - [ ] I have added necessary documentation (if applicable) 26 | - [ ] I have verified that the installer still works with the underlying CLI 27 | 28 | --- 29 | 30 | ## Additional Notes 31 | 32 | Any other information that reviewers should know, including limitations, concerns, or context about the change. 33 | -------------------------------------------------------------------------------- /Jellyfin2Samsung-CrossOS/app.manifest: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | 7 | 8 | 9 | 10 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /Jellyfin2Samsung-CrossOS/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleName 6 | Jellyfin2Samsung 7 | CFBundleDisplayName 8 | Jellyfin2Samsung 9 | CFBundleIdentifier 10 | com.madebypatrick.jellyfin2samsung 11 | CFBundleVersion 12 | 1.8.0-beta 13 | CFBundlePackageType 14 | APPL 15 | CFBundleSignature 16 | ???? 17 | CFBundleExecutable 18 | Jellyfin2Samsung 19 | CFBundleIconFile 20 | jelly2sams.icns 21 | LSMinimumSystemVersion 22 | 10.15 23 | NSHighResolutionCapable 24 | 25 | NSSupportsAutomaticGraphicsSwitching 26 | 27 | 28 | -------------------------------------------------------------------------------- /Jellyfin2Samsung-CrossOS/Models/JellyfinPluginInfo.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace Jellyfin2Samsung.Models 5 | { 6 | public class JellyfinPluginInfo 7 | { 8 | public string Name { get; set; } 9 | public string Id { get; set; } 10 | } 11 | 12 | public class PluginMatrixEntry 13 | { 14 | public string Name { get; set; } 15 | public string IdContains { get; set; } 16 | public string ServerPath { get; set; } 17 | public List ExplicitServerFiles { get; set; } 18 | public List FallbackUrls { get; set; } 19 | public bool UseBabel { get; set; } 20 | public bool RequiresModuleBundle { get; set; } 21 | public string ModuleRepoApiRoot { get; set; } 22 | public string ModuleBundleFileName { get; set; } 23 | } 24 | public class ExtractedDomBlocks 25 | { 26 | public List HeadInjectBlocks { get; set; } = new(); 27 | public List BodyInjectBlocks { get; set; } = new(); 28 | } 29 | } -------------------------------------------------------------------------------- /Jellyfin2Samsung-CrossOS/Helpers/StatusToColorConverter.cs: -------------------------------------------------------------------------------- 1 | using Avalonia.Data.Converters; 2 | using Avalonia.Media; 3 | using Jellyfin2Samsung.Models; 4 | using System; 5 | using System.Globalization; 6 | 7 | namespace Jellyfin2Samsung.Helpers 8 | { 9 | public class StatusToColorConverter : IValueConverter 10 | { 11 | public object Convert(object? value, Type targetType, object? parameter, CultureInfo culture) 12 | { 13 | return value switch 14 | { 15 | TvLogConnectionStatus.Connected => new SolidColorBrush(Color.Parse("#27AE60")), 16 | TvLogConnectionStatus.Listening => new SolidColorBrush(Color.Parse("#2980B9")), 17 | TvLogConnectionStatus.NoConnections => new SolidColorBrush(Color.Parse("#E67E22")), 18 | TvLogConnectionStatus.Stopped => new SolidColorBrush(Color.Parse("#7F8C8D")), 19 | _ => Brushes.Gray 20 | }; 21 | } 22 | 23 | public object ConvertBack(object? value, Type targetType, object? parameter, CultureInfo culture) 24 | => throw new NotSupportedException(); 25 | } 26 | } -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2025 Patrick Stel 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 | -------------------------------------------------------------------------------- /.github/SECURITY.md: -------------------------------------------------------------------------------- 1 | # Security Policy 2 | 3 | ## Reporting a Vulnerability 4 | 5 | If you discover a security vulnerability in **Samsung‑Jellyfin‑Installer**, please report it via the [GitHub Issues](https://github.com/PatrickSt1991/Samsung-Jellyfin-Installer/issues) page. 6 | 7 | Include as much information as possible: 8 | - Version of the installer you are using 9 | - Your OS and environment 10 | - Steps to reproduce the issue 11 | - Any logs or error messages 12 | 13 | > Note: This project is primarily a GUI wrapper around the Tizen CLI. Vulnerabilities are most likely in the underlying CLI tool. When reporting, please clarify whether the issue is in the installer or the CLI itself. 14 | 15 | --- 16 | 17 | ## Supported Versions 18 | 19 | Please indicate the installer version when reporting security issues. 20 | 21 | --- 22 | 23 | ## Security Updates 24 | 25 | Security fixes will be addressed in regular releases. Users are encouraged to keep their installations up-to-date. 26 | 27 | --- 28 | 29 | ## Responsible Disclosure 30 | 31 | We appreciate responsible disclosure. Avoid publishing exploits publicly until the issue has been addressed to protect users. 32 | -------------------------------------------------------------------------------- /Jellyfin2Samsung-CrossOS/Models/NetworkDevice.cs: -------------------------------------------------------------------------------- 1 | namespace Jellyfin2Samsung.Models 2 | { 3 | public class NetworkDevice 4 | { 5 | public required string IpAddress { get; set; } 6 | public string? Manufacturer { get; set; } 7 | public string? DeviceName { get; set; } 8 | public string? ModelName { get; set; } 9 | public string? DeveloperMode { get; set; } 10 | public string? DeveloperIP { get; set; } 11 | 12 | public string DisplayText 13 | { 14 | get 15 | { 16 | if (DeviceName is not null && ModelName is not null) 17 | return $"{IpAddress} | {ModelName} | {DeviceName}"; 18 | 19 | if (DeviceName is not null) 20 | return $"{IpAddress} | {DeviceName}"; 21 | 22 | if (Manufacturer is not null) 23 | return $"{IpAddress} | {Manufacturer}"; 24 | 25 | return IpAddress; 26 | } 27 | } 28 | } 29 | public class ExtensionEntry 30 | { 31 | public int Index; 32 | public string Name = ""; 33 | public bool Activated; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /Jellyfin2Samsung-CrossOS.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 17 4 | VisualStudioVersion = 17.14.36511.14 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Jellyfin2Samsung", "Jellyfin2Samsung-CrossOS\Jellyfin2Samsung.csproj", "{0D305441-51D6-413D-8108-8C85CC0E2CF1}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|Any CPU = Debug|Any CPU 11 | Release|Any CPU = Release|Any CPU 12 | EndGlobalSection 13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 14 | {0D305441-51D6-413D-8108-8C85CC0E2CF1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 15 | {0D305441-51D6-413D-8108-8C85CC0E2CF1}.Debug|Any CPU.Build.0 = Debug|Any CPU 16 | {0D305441-51D6-413D-8108-8C85CC0E2CF1}.Release|Any CPU.ActiveCfg = Release|Any CPU 17 | {0D305441-51D6-413D-8108-8C85CC0E2CF1}.Release|Any CPU.Build.0 = Release|Any CPU 18 | EndGlobalSection 19 | GlobalSection(SolutionProperties) = preSolution 20 | HideSolutionNode = FALSE 21 | EndGlobalSection 22 | GlobalSection(ExtensibilityGlobals) = postSolution 23 | SolutionGuid = {E5C5188A-9FB7-44EB-8003-4624B356498F} 24 | EndGlobalSection 25 | EndGlobal 26 | -------------------------------------------------------------------------------- /.github/jellyfin-tizen-logo.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /Jellyfin2Samsung-CrossOS/Assets/TizenProfile/ca/author_ca.cer: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIDdTCCAl2gAwIBAgICaFYwDQYJKoZIhvcNAQELBQAwXjEaMBgGA1UECgwRVGl6 3 | ZW4gQXNzb2NpYXRpb24xGjAYBgNVBAsMEVRpemVuIEFzc29jaWF0aW9uMSQwIgYD 4 | VQQDDBtUaXplbiBEZXZlbG9wZXJzIFJvb3QgQ2xhc3MwHhcNMTUwMjEwMDEwNDAx 5 | WhcNMzAwMjA2MDEwNDAxWjCBijELMAkGA1UEBhMCS1IxFDASBgNVBAgTC1NvdXRo 6 | IEtvcmVhMQ4wDAYDVQQHEwVTdXdvbjEmMCQGA1UEChMdU2Ftc3VuZyBFbGVjdHJv 7 | bmljcyBDby4sIEx0ZC4xCzAJBgNVBAsTAlZEMSAwHgYDVQQDExdTYW1zdW5nIEF1 8 | dGhvciBDQSBDbGFzczCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAK/i 9 | LAudLDIHXfqj5iLi/Izdo4rXMUdbkXYu9az9TgGfUqOmJi203kFFG1T5TQJfVMaB 10 | vry+MKLYPzIUWsTcrjelDYVTWmEMucxm1lJvX0drZfXdi/EK7TzWEr0sR7ZR4cQu 11 | Mgv80edK+H0ppFturPumrh/u8yVqTIHQQhfYbOIjW4939BdO5IG03F+8SrN5Udoe 12 | /YCtKPS3najZRxx3WqITVvV3AEKd2CualD/9y4Y+y+V7m90habypqWX2rnoMk5AG 13 | 86wFyADkzEv0zoIve//atS2cHRGJx7Com/XXU8OBSsDavwf+6h5AVRzr9ETcPTYo 14 | Rrqt0g5h++xyckvGJKcCAwEAAaMQMA4wDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0B 15 | AQsFAAOCAQEAM4cZsU/keJf7D7blzloKbt2a+iuVs6AVR0P/OjB49vmFyozm8oZR 16 | cWmxzFSb4+yz5GOjCZtpynKgJWfQzL8JZ8zJW8OfMznRFn+sGDMvX3XsDrKkwsrt 17 | V0rs5E8WMqYmvH1TmFI9SvP3wgV/nKObF2mgyzZC+czZsfUSyNSJxOduNreLA111 18 | I7Zyibq+ulwrEs9EltuetBDih2g6XXH60ggXAr7myuCgfn8IW6zSZB3oA0Vc/CIO 19 | P9UEfm0LhrW28RgtDMWOXz8QygtMoKZ6R9TrG9S7cJP0rWeZisyQ7LE4Aasrk7HN 20 | Yn1Be+g2m4cUTvs6fLLwyQpARYZJwRHBMg== 21 | -----END CERTIFICATE----- 22 | -------------------------------------------------------------------------------- /jellyfin-tizen-logo.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /Jellyfin2Samsung-CrossOS/Views/InstallingWindow.axaml: -------------------------------------------------------------------------------- 1 | 15 | 16 | 18 | 19 | 24 | 25 | 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /Jellyfin2Samsung-CrossOS/Assets/TizenProfile/ca/public2.crt: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIDrTCCApWgAwIBAgIBATANBgkqhkiG9w0BAQsFADCBkTELMAkGA1UEBhMCS1Ix 3 | FDASBgNVBAgMC1NvdXRoIEtvcmVhMQ4wDAYDVQQHDAVTdXdvbjEmMCQGA1UECgwd 4 | U2Ftc3VuZyBFbGVjdHJvbmljcyBDby4sIEx0ZC4xCzAJBgNVBAsMAlZEMScwJQYD 5 | VQQDDB5WRCBERVZFTE9QRVIgUHVibGljIFJvb3QgQ2xhc3MwHhcNMTQxMjE5MDky 6 | OTQyWhcNMjkxMjE1MDkyOTQyWjCBjzELMAkGA1UEBhMCS1IxFDASBgNVBAgMC1Nv 7 | dXRoIEtvcmVhMQ4wDAYDVQQHDAVTdXdvbjEmMCQGA1UECgwdU2Ftc3VuZyBFbGVj 8 | dHJvbmljcyBDby4sIEx0ZC4xCzAJBgNVBAsMAlZEMSUwIwYDVQQDDBxWRCBERVZF 9 | TE9QRVIgUHVibGljIENBIENsYXNzMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB 10 | CgKCAQEAr9u+prHP0MtGDqQmDtIpFuFKD1mCmYPEA4OZ6zRH3f3t9cUmXtmAGEDP 11 | inCHpw9UdGU3JkNnNUd6dFf2HkFBIm8+LepRxR/rEmkHsBHFaLbTDVNZnwBXVs82 12 | eyMl9wonLp74otysnLAtEA968r7MH5WwwkF73W2vtOqA+PpGOH31LAeLFNPajAVC 13 | gqiaIKn8eFQuLta2dNrXcZXia+GTXz0PZ0oEs6k1cphhkbe+uV5NL/qWDjF5X1rI 14 | Gxz/58AwxfF73wP7QPY9Z34vwai0tcUvGAkNXW60FjTj6iZ2N/UxPsuhNa1sSv2s 15 | rxhWSBAklC3L4A9C6o8sP91WkkdXIQIDAQABoxAwDjAMBgNVHRMEBTADAQH/MA0G 16 | CSqGSIb3DQEBCwUAA4IBAQCnzmtVT7Zr8BjemLmZu/mLmGizAl/QaufSyCLaPVnU 17 | lgdReeMdjBvtvNlM9/EJecxiWhAakiZFA664lisAjQjL3bREP9HjOSSDhvx8GNLi 18 | gjRKOJVivFxz0E4C7K/d9wBlstNCsTe2dRW0mhV+7l1kvbqByfi3kzUrJxaTOev/ 19 | DxaPs9qofe/+Fvor5AcQXiKJ7wuva5HvYZq1z3f3XuEy/tIhv2fkto09aZTNHNje 20 | HeqiAUQFNrtv8NbHQZZKKaZQbnrT2h4HjtfuzAHaFt1EaO7l2TRE+OEJIpSkKT08 21 | 1kT1zqSmnj38acW/+ExcY7fABrT3oigLsXPBsYxjSAtn 22 | -----END CERTIFICATE----- 23 | -------------------------------------------------------------------------------- /Jellyfin2Samsung-CrossOS/Views/TvLogsWindow.axaml.cs: -------------------------------------------------------------------------------- 1 | using Avalonia; 2 | using Avalonia.Controls; 3 | using Avalonia.Threading; 4 | using Jellyfin2Samsung.ViewModels; 5 | using System; 6 | using System.ComponentModel; 7 | 8 | namespace Jellyfin2Samsung.Views; 9 | 10 | public partial class TvLogsWindow : Window 11 | { 12 | private TvLogsViewModel? _viewModel; 13 | 14 | public TvLogsWindow() 15 | { 16 | InitializeComponent(); 17 | 18 | DataContextChanged += OnDataContextChanged; 19 | } 20 | 21 | private void OnDataContextChanged(object? sender, EventArgs e) 22 | { 23 | // Unhook old VM 24 | if (_viewModel != null) 25 | { 26 | _viewModel.PropertyChanged -= OnViewModelPropertyChanged; 27 | } 28 | 29 | _viewModel = DataContext as TvLogsViewModel; 30 | 31 | // Hook new VM 32 | if (_viewModel != null) 33 | { 34 | _viewModel.PropertyChanged += OnViewModelPropertyChanged; 35 | } 36 | } 37 | 38 | private void OnViewModelPropertyChanged(object? sender, PropertyChangedEventArgs e) 39 | { 40 | if (e.PropertyName == nameof(TvLogsViewModel.Logs)) 41 | { 42 | Dispatcher.UIThread.Post(() => 43 | LogScrollViewer.ScrollToEnd()); 44 | } 45 | } 46 | 47 | private void OnCloseClick(object? sender, Avalonia.Interactivity.RoutedEventArgs e) 48 | { 49 | Close(); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /Jellyfin2Samsung-CrossOS/ViewModels/IpInputDialogViewModel.cs: -------------------------------------------------------------------------------- 1 | using CommunityToolkit.Mvvm.ComponentModel; 2 | using CommunityToolkit.Mvvm.Input; 3 | using Jellyfin2Samsung.Interfaces; 4 | using System; 5 | 6 | namespace Jellyfin2Samsung.ViewModels 7 | { 8 | public partial class IpInputDialogViewModel : ObservableObject 9 | { 10 | private readonly ILocalizationService _localization; 11 | private readonly Action _close; 12 | 13 | [ObservableProperty] 14 | private string? enteredIp; 15 | 16 | public string Title => _localization.GetString("IpWindowTitle"); 17 | public string Message => _localization.GetString("IpWindowDescription"); 18 | public string OkText => _localization.GetString("keyConfirm"); 19 | public string CancelText => _localization.GetString("keyStop"); 20 | public IRelayCommand OkCommand { get; } 21 | public IRelayCommand CancelCommand { get; } 22 | 23 | public IpInputDialogViewModel(ILocalizationService localization, Action close) 24 | { 25 | _localization = localization ?? throw new ArgumentNullException(nameof(localization)); 26 | _close = close ?? throw new ArgumentNullException(nameof(close)); 27 | 28 | OkCommand = new RelayCommand(OnOk); 29 | CancelCommand = new RelayCommand(OnCancel); 30 | } 31 | 32 | private void OnOk() => _close(true); 33 | 34 | private void OnCancel() => _close(false); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /Jellyfin2Samsung-CrossOS/Assets/TizenProfile/ca/vd_tizen_dev_author_ca.cer: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIEfzCCA2egAwIBAgIEaFN6QzANBgkqhkiG9w0BAQ0FADBeMRowGAYDVQQKDBFU 3 | aXplbiBBc3NvY2lhdGlvbjEaMBgGA1UECwwRVGl6ZW4gQXNzb2NpYXRpb24xJDAi 4 | BgNVBAMMG1RpemVuIERldmVsb3BlcnMgUm9vdCBDbGFzczAeFw0yNTA2MTkwNDI2 5 | MzhaFw00MDA2MTkwNDI2MzhaMIGSMQswCQYDVQQGEwJLUjEaMBgGA1UECAwRUmVw 6 | dWJsaWMgb2YgS29yZWExEzARBgNVBAcMClN1d29uIENpdHkxJjAkBgNVBAoMHVNh 7 | bXN1bmcgRWxlY3Ryb25pY3MgQ28uLCBMdGQuMQswCQYDVQQLDAJWRDEdMBsGA1UE 8 | AwwUU2Ftc3VuZyBWRCBBdXRob3IgQ0EwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAw 9 | ggIKAoICAQCNLJUDeRdCsRgFNc0VW3Jwx1V/H9EcNmuA0RwLqyJyurv0pRyClBSh 10 | iPBBnJP+rt91k9zhqpTp5r/8xUnIWyyuCd7PassOp4po3ZiLv/0yFclSjIpYIOHY 11 | yIHZkamCm6+L5fSmOzXnzwRId/1rb2LKuz9AP3Hk9I0TSYxlSFbz0jkbAxvcGgrZ 12 | A6siohXUwKRxWfhZTpPQsWd9ZtNRQmg6XYouK9h06TxJ8mYHIpvaDwfnxFPtYdAj 13 | ljCAjUr/UdNPKnC13JCWTCDQXK5ZPSbLxQZD5tDbZSw7kjXFGIHts8bQDN2knMqa 14 | l1dzZjpa5pvrRiWeimg59duMMKzs8l96Hap+13ND6+sN+0gvFc4JuzBUoqRaQqW/ 15 | WHl7d1+ySC0z2KUhc4bRUK28rT8fWJ0YkDpxjTvxuM6qdaDnraPnJO6Cze1MoD7y 16 | CDcLkWUmMOv8yxD1cpZcWN7ZMlUzKt73TqHce9zxkvo5QB3VsXPC8H5LP32vRB03 17 | XBhqL6yDDejioyEtpgn3WOdkHz6sJqTvoKe8fSoEa+S6SXctsVBI5RMToq9q20rN 18 | jCSVGur56WVc8jkXuc3RSxgFzMx3RVunfy12hQnbFTWPwfPFS+YO/eHC2w6O9nB9 19 | sm7lHsm+PPc5Nrxty7AS/qVvwLPlkgDwPF7U4LT90ycz+wYHC8LIRwIDAQABoxAw 20 | DjAMBgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBDQUAA4IBAQBNSFmmWl9AjcxAyNWQ 21 | BlO8/Wrc70MlB2JpZ55Vuw2e8rQvWmBC5SjNRHmIu57HgMMGuj0oudCjH/fUkIIk 22 | 4XC8DMAj82wUMPKHaihDzylEtj4Otti1SNNjdCIvVPJg3FzcqWR/8xxrYrfoAWsS 23 | 2eTTFpx2Ogc3n4XevbwfDPQiWZhE88cbuzWcHIBbwRVU4kjEdFXcsuj6hLijMXkd 24 | /BFgtUOhpo+5H3OnLKdl9yjovOP9A4H3/Ip1ptM7QskVNjLdgJ8wSzZvFSVrYL7O 25 | ft82Jy86eKrQ9kDg46qaDbBfUzRs8akbSfImsskYO97EB+GXbtx92EBhBSHFKe/G 26 | AM0p 27 | -----END CERTIFICATE----- 28 | -------------------------------------------------------------------------------- /Jellyfin2Samsung-CrossOS/Models/GitHubRelease.cs: -------------------------------------------------------------------------------- 1 | using Newtonsoft.Json; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | 5 | 6 | namespace Jellyfin2Samsung.Models 7 | { 8 | 9 | public class GitHubRelease 10 | { 11 | [JsonProperty("url")] 12 | public string Url { get; set; } 13 | [JsonProperty("name")] 14 | public string Name { get; set; } 15 | 16 | [JsonProperty("tag_name")] 17 | public string TagName { get; set; } 18 | 19 | [JsonProperty("published_at")] 20 | public string PublishedAt { get; set; } 21 | 22 | [JsonProperty("assets")] 23 | public List Assets { get; set; } = new List(); 24 | 25 | public string PrimaryDownloadUrl => Assets?.FirstOrDefault()?.DownloadUrl; 26 | [JsonConstructor] 27 | public GitHubRelease() 28 | { 29 | } 30 | } 31 | 32 | public class Asset 33 | { 34 | [JsonProperty("name")] 35 | public string FileName { get; set; } 36 | 37 | [JsonProperty("browser_download_url")] 38 | public string DownloadUrl { get; set; } 39 | 40 | [JsonProperty("size")] 41 | public long Size { get; set; } 42 | 43 | public string DisplayText => $"{FileName} ({FormatFileSize(Size)})"; 44 | 45 | private string FormatFileSize(long bytes) 46 | { 47 | string[] sizes = { "B", "KB", "MB", "GB" }; 48 | int order = 0; 49 | double len = bytes; 50 | while (len >= 1024 && order < sizes.Length - 1) 51 | { 52 | order++; 53 | len /= 1024; 54 | } 55 | return $"{len:0.##} {sizes[order]}"; 56 | } 57 | [JsonConstructor] 58 | public Asset() 59 | { 60 | } 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /Jellyfin2Samsung-CrossOS/Assets/TizenProfile/ca/vd_tizen_dev_public2.crt: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIEvDCCA6SgAwIBAgIQEFcJZvLWjnZy2s9RsDWhmTANBgkqhkiG9w0BAQ0FADCB 3 | kTELMAkGA1UEBhMCS1IxFDASBgNVBAgMC1NvdXRoIEtvcmVhMQ4wDAYDVQQHDAVT 4 | dXdvbjEmMCQGA1UECgwdU2Ftc3VuZyBFbGVjdHJvbmljcyBDby4sIEx0ZC4xCzAJ 5 | BgNVBAsMAlZEMScwJQYDVQQDDB5WRCBERVZFTE9QRVIgUHVibGljIFJvb3QgQ2xh 6 | c3MwHhcNMjUwNjE3MTAyMDEyWhcNMjkwNjE2MjEwMDAwWjCBjzELMAkGA1UEBhMC 7 | S1IxFDASBgNVBAgMC1NvdXRoIEtvcmVhMQ4wDAYDVQQHDAVTdXdvbjEmMCQGA1UE 8 | CgwdU2Ftc3VuZyBFbGVjdHJvbmljcyBDby4sIEx0ZC4xCzAJBgNVBAsMAlZEMSUw 9 | IwYDVQQDDBxWRCBERVZFTE9QRVIgUHVibGljIENBIENsYXNzMIICIjANBgkqhkiG 10 | 9w0BAQEFAAOCAg8AMIICCgKCAgEAymA8xOpycAu11WBrw4n2+mIdXfA9jzgEI3wY 11 | dn7o2o4H5o22jihR8aEpsrhW+GTgi+90GxUGwO+o/Nwp5IFp2alNyunF251uVmsj 12 | 1WtHBdWy31ex811H6dR0EfJeK5Ksb0XoOLbQP0+K6UM6ojXpYk1Q0aWBoIYDImgu 13 | 4zsB75Q30KGVlYqvvUtr0KVNao9LhPLWda3hqe2qwFZSwd1d9N+hHO6xPrtnjO2c 14 | x63kPeWJ3GLmO/0phb+UdMQcGJ2KBpApb/WhN+uDjucvAOwbMFOU3NymS7BWZzS6 15 | /Rca8WEJkY0XBGndUaniYiqOUisQ5aP8I5HIP9EoM/wtk/ldy1CVckX1DyI1o/ZU 16 | QWPXzPsb0/cmKOB1N33CFvejvsrJDipIMUW8TgB5qw/WHbiOlyxPDc+G8LjJ2ww1 17 | wFw9dGVIYpAslcXGyk7r0gHW939mJhUIwP9xZYwGdPKSgjHgjAZrWWrE4D1KqEay 18 | HVLRhLdhYisHPuqmtuEdbXg32yxCeONdSEz0Z7I2CYn9RKIwBzkuWGjwtCyrvocp 19 | 0AKANve64h0AV1ttlt4hwLbbnLrFtlF1RMFv6mcnz8pg6sLHLcKoqVJ50X9ZvMCC 20 | j22rlO0FUZ36M1CiV9HJIxH/WoPjftHHuwF+CuJv2kNZuwjTB8dtYpg5PK2sEimB 21 | 4oJomS8CAwEAAaMQMA4wDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQ0FAAOCAQEA 22 | DtwJOvOAbqqgiLzR9cD6HQ2Fofjcoyj69XjduhL5syzx82ASu2GeZDYOApG9Uwmb 23 | 1w1hXl/UHUFHp0Ob/6SV2wXJTZbBMQlOaYEYwB1crToTfSMTJ5t6LuR+mRQvdBHL 24 | FM94fRQjQz3ZZOtMsq2WvcWN7ZEUDK1KMh+RP5e7z1GlHCJ00lGqNMrqVf0AMRm3 25 | iYfT+46/+CL3IY3iWbn2g3e8mPr0U4ZBpAdWawfHRX21oTCU3b5rJ/s1G7dcvkqk 26 | vu74HrY4f0dpiRCctgdcVuQnWOPFIlLJEkYOiQV1c5Ro/cWUMCo0oR4icvHXb4dP 27 | Fy+35NUwLfcmza3lFdLgrQ== 28 | -----END CERTIFICATE----- 29 | -------------------------------------------------------------------------------- /Jellyfin2Samsung-CrossOS/ViewModels/InstallationCompleteViewModel.cs: -------------------------------------------------------------------------------- 1 | using Avalonia; 2 | using Avalonia.Controls.ApplicationLifetimes; 3 | using CommunityToolkit.Mvvm.ComponentModel; 4 | using CommunityToolkit.Mvvm.Input; 5 | using Jellyfin2Samsung.Interfaces; 6 | using System; 7 | using System.Diagnostics; 8 | 9 | 10 | namespace Jellyfin2Samsung.ViewModels 11 | { 12 | public partial class InstallationCompleteViewModel : ObservableObject 13 | { 14 | private readonly ILocalizationService _localization; 15 | 16 | public InstallationCompleteViewModel(ILocalizationService localization) 17 | { 18 | _localization = localization; 19 | } 20 | 21 | public string Title => _localization.GetString("InstallationSuccessful"); 22 | public string SuccessMessage => _localization.GetString("InstallationSuccessfulOn"); 23 | public string EasyRight => _localization.GetString("lbleasyRight"); 24 | public string Validation => _localization.GetString("lblValidation"); 25 | public string Close => _localization.GetString("btn_Close"); 26 | 27 | [RelayCommand] 28 | private async void OpenKoFi() 29 | { 30 | try 31 | { 32 | var url = "https://ko-fi.com/patrickst"; 33 | var psi = new ProcessStartInfo 34 | { 35 | FileName = url, 36 | UseShellExecute = true 37 | }; 38 | Process.Start(psi); 39 | } 40 | catch (Exception ex) 41 | { 42 | Console.WriteLine($"Failed to open URL: {ex.Message}"); 43 | } 44 | CloseWindow(); 45 | } 46 | 47 | [RelayCommand] 48 | private void CloseWindow() 49 | { 50 | if (Application.Current.ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop) 51 | { 52 | desktop.Shutdown(); 53 | } 54 | } 55 | 56 | public event EventHandler? RequestClose; 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /Jellyfin2Samsung-CrossOS/Styles/Buttons.axaml: -------------------------------------------------------------------------------- 1 | 3 | 7 | 17 | 20 | 30 | 33 | 48 | 53 | 56 | 57 | -------------------------------------------------------------------------------- /Jellyfin2Samsung-CrossOS/Helpers/CipherUtil.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq; 3 | using System.Security.Cryptography; 4 | using System.Text; 5 | 6 | namespace Jellyfin2Samsung.Helpers 7 | { 8 | public class CipherUtil 9 | { 10 | private const string KeyString = "KYANINYLhijklmnopqrstuvwx"; 11 | 12 | private byte[] KeyBytes => Encoding.UTF8.GetBytes(KeyString).Take(24).ToArray(); 13 | 14 | public string GetEncryptedString(string plainText) 15 | { 16 | using var tdes = new TripleDESCryptoServiceProvider 17 | { 18 | Key = KeyBytes, 19 | Mode = CipherMode.ECB, 20 | Padding = PaddingMode.PKCS7 21 | }; 22 | 23 | var data = Encoding.UTF8.GetBytes(plainText); 24 | byte[] encrypted = tdes.CreateEncryptor().TransformFinalBlock(data, 0, data.Length); 25 | return Convert.ToBase64String(encrypted); 26 | } 27 | public string GetDecryptedString(string encryptedBase64) 28 | { 29 | byte[] encryptedBytes = Convert.FromBase64String(encryptedBase64); 30 | 31 | using var tripleDes = TripleDES.Create(); 32 | tripleDes.Key = KeyBytes; 33 | tripleDes.Mode = CipherMode.ECB; 34 | tripleDes.Padding = PaddingMode.PKCS7; 35 | 36 | byte[] decrypted = tripleDes.CreateDecryptor().TransformFinalBlock(encryptedBytes, 0, encryptedBytes.Length); 37 | return Encoding.UTF8.GetString(decrypted); 38 | } 39 | public string GenerateRandomPassword(int length = 12) 40 | { 41 | if (length < 8) 42 | throw new ArgumentException("Password must be at least 8 characters long."); 43 | 44 | const string upper = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; 45 | const string lower = "abcdefghijklmnopqrstuvwxyz"; 46 | const string digits = "0123456789"; 47 | const string all = upper + lower + digits; 48 | 49 | var randomBytes = new byte[length]; 50 | using var rng = RandomNumberGenerator.Create(); 51 | rng.GetBytes(randomBytes); 52 | 53 | var chars = new char[length]; 54 | chars[0] = upper[randomBytes[0] % upper.Length]; 55 | chars[1] = lower[randomBytes[1] % lower.Length]; 56 | chars[2] = digits[randomBytes[2] % digits.Length]; 57 | 58 | for (int i = 3; i < length; i++) 59 | chars[i] = all[randomBytes[i] % all.Length]; 60 | 61 | return new string(chars.OrderBy(_ => Guid.NewGuid()).ToArray()); 62 | } 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /.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 | -------------------------------------------------------------------------------- /Jellyfin2Samsung-CrossOS/Views/IpInputDialog.axaml: -------------------------------------------------------------------------------- 1 | 18 | 19 | 25 | 26 | 31 | 32 | 33 | 34 | 35 | 36 | 41 | 42 | 43 | 48 | 49 | 50 | 59 | 60 | 61 | 64 |