using ClawdDotNet.Models; using CommunityToolkit.Mvvm.ComponentModel; using CommunityToolkit.Mvvm.Input; namespace ClawdDotNet.Desktop.ViewModels; public sealed partial class ToolSettingsViewModel : ViewModelBase { public string ToolName { get; } public object? SettingsObject { get; } // FTP [ObservableProperty] private string _ftpHost = ""; [ObservableProperty] private int _ftpPort = 21; [ObservableProperty] private string _ftpUsername = ""; [ObservableProperty] private string _ftpPassword = ""; [ObservableProperty] private string _ftpRootPath = "./data/"; // Mail [ObservableProperty] private string _mailUsername = ""; [ObservableProperty] private string _mailPassword = ""; [ObservableProperty] private string _mailImapHost = ""; [ObservableProperty] private int _mailImapPort = 993; [ObservableProperty] private string _mailSmtpHost = ""; [ObservableProperty] private int _mailSmtpPort = 587; [ObservableProperty] private string _mailAllowedRecipients = ""; // Database [ObservableProperty] private DatabaseType _dbType = DatabaseType.MySql; [ObservableProperty] private string _dbConnectionString = ""; [ObservableProperty] private DatabaseAccessLevel _dbAccessLevel = DatabaseAccessLevel.ReadOnly; [ObservableProperty] private string _dbAllowedTables = ""; // Telegram [ObservableProperty] private string _telegramBotToken = ""; [ObservableProperty] private string _telegramDefaultChatId = ""; [ObservableProperty] private string _telegramAllowedChatIds = ""; // DirectAPI [ObservableProperty] private string _directApiDefaultProvider = "twelvedata"; [ObservableProperty] private int _directApiCacheTtlSeconds = 60; [ObservableProperty] private string _directApiTwelveDataKey = ""; [ObservableProperty] private string _directApiAlphaVantageKey = ""; // WebFetch [ObservableProperty] private string _webFetchAllowedDomains = ""; [ObservableProperty] private int _webFetchMaxResponseKb = 512; [ObservableProperty] private string _webFetchUserAgent = "ClawdDotNet-Agent/1.0"; // SocialMediaManager [ObservableProperty] private string _smmXApiKey = ""; [ObservableProperty] private string _smmXWatchAccounts = ""; [ObservableProperty] private string _smmRedditWatchSubreddits = ""; [ObservableProperty] private int _smmRedditPostLimit = 15; [ObservableProperty] private string _smmOpenRouterApiKey = ""; [ObservableProperty] private string _smmSttModel = "openai/whisper-1"; [ObservableProperty] private string _smmYoutubeChannels = ""; // FileRW [ObservableProperty] private string _fileRwPersonalAllowedExtensions = ".txt,.json,.md,.html,.js,.css"; [ObservableProperty] private FileRWAccessLevel _fileRwSharedAccessLevel = FileRWAccessLevel.Denied; [ObservableProperty] private string _fileRwSharedAllowedExtensions = ".txt,.json,.md"; [ObservableProperty] private string _fileRwProtectedPaths = "stocks/"; public List DbTypes { get; } = [DatabaseType.MySql, DatabaseType.Postgres, DatabaseType.MsSql, DatabaseType.MongoDb]; public List DbAccessLevels { get; } = [DatabaseAccessLevel.ReadOnly, DatabaseAccessLevel.ReadWrite, DatabaseAccessLevel.Admin]; public List FileRwAccessLevels { get; } = [FileRWAccessLevel.Denied, FileRWAccessLevel.Read, FileRWAccessLevel.ReadWrite, FileRWAccessLevel.Admin]; public Dictionary? Result { get; private set; } public event Action? CloseRequested; public ToolSettingsViewModel() : this("FTP", new()) { } public ToolSettingsViewModel(string toolName, Dictionary config) { ToolName = toolName; SettingsObject = ToolSettingsFactory.CreateViewModel(toolName, config); switch (SettingsObject) { case FTPToolSettings ftp: FtpHost = ftp.Host; FtpPort = ftp.Port; FtpUsername = ftp.Username; FtpPassword = ftp.Password; FtpRootPath = ftp.RootPath; break; case MailToolSettings mail: MailUsername = mail.Username; MailPassword = mail.Password; MailImapHost = mail.ImapHost; MailImapPort = mail.ImapPort; MailSmtpHost = mail.SmtpHost; MailSmtpPort = mail.SmtpPort; MailAllowedRecipients = mail.AllowedRecipients; break; case DatabaseToolSettings db: DbType = db.Type; DbConnectionString = db.ConnectionString; DbAccessLevel = db.AccessLevel; DbAllowedTables = db.AllowedTables; break; case TelegramToolSettings tg: TelegramBotToken = tg.BotToken; TelegramDefaultChatId = tg.DefaultChatId; TelegramAllowedChatIds = tg.AllowedChatIds; break; case DirectAPIToolSettings dapi: DirectApiDefaultProvider = dapi.DefaultProvider; DirectApiCacheTtlSeconds = dapi.CacheTtlSeconds; DirectApiTwelveDataKey = dapi.TwelveDataKey; DirectApiAlphaVantageKey = dapi.AlphaVantageKey; break; case WebFetchToolSettings wf: WebFetchAllowedDomains = wf.AllowedDomains; WebFetchMaxResponseKb = wf.MaxResponseKb; WebFetchUserAgent = wf.UserAgent; break; case SocialMediaManagerToolSettings smm: SmmXApiKey = smm.XApiKey; SmmXWatchAccounts = smm.XWatchAccounts; SmmRedditWatchSubreddits = smm.RedditWatchSubreddits; SmmRedditPostLimit = smm.RedditPostLimit; SmmOpenRouterApiKey = smm.OpenRouterApiKey; SmmSttModel = smm.STTModel; SmmYoutubeChannels = smm.YoutubeChannels; break; case FileRWToolSettings frw: FileRwPersonalAllowedExtensions = frw.PersonalAllowedExtensions; FileRwSharedAccessLevel = frw.SharedAccessLevel; FileRwSharedAllowedExtensions = frw.SharedAllowedExtensions; FileRwProtectedPaths = frw.ProtectedPaths; break; } } [RelayCommand] private void Confirm() { switch (SettingsObject) { case FTPToolSettings ftp: ftp.Host = FtpHost; ftp.Port = FtpPort; ftp.Username = FtpUsername; ftp.Password = FtpPassword; ftp.RootPath = FtpRootPath; break; case MailToolSettings mail: mail.Username = MailUsername; mail.Password = MailPassword; mail.ImapHost = MailImapHost; mail.ImapPort = MailImapPort; mail.SmtpHost = MailSmtpHost; mail.SmtpPort = MailSmtpPort; mail.AllowedRecipients = MailAllowedRecipients; break; case DatabaseToolSettings db: db.Type = DbType; db.ConnectionString = DbConnectionString; db.AccessLevel = DbAccessLevel; db.AllowedTables = DbAllowedTables; break; case TelegramToolSettings tg: tg.BotToken = TelegramBotToken; tg.DefaultChatId = TelegramDefaultChatId; tg.AllowedChatIds = TelegramAllowedChatIds; break; case DirectAPIToolSettings dapi: dapi.DefaultProvider = DirectApiDefaultProvider; dapi.CacheTtlSeconds = DirectApiCacheTtlSeconds; dapi.TwelveDataKey = DirectApiTwelveDataKey; dapi.AlphaVantageKey = DirectApiAlphaVantageKey; break; case WebFetchToolSettings wf: wf.AllowedDomains = WebFetchAllowedDomains; wf.MaxResponseKb = WebFetchMaxResponseKb; wf.UserAgent = WebFetchUserAgent; break; case SocialMediaManagerToolSettings smm: smm.XApiKey = SmmXApiKey; smm.XWatchAccounts = SmmXWatchAccounts; smm.RedditWatchSubreddits = SmmRedditWatchSubreddits; smm.RedditPostLimit = SmmRedditPostLimit; smm.OpenRouterApiKey = SmmOpenRouterApiKey; smm.STTModel = SmmSttModel; smm.YoutubeChannels = SmmYoutubeChannels; break; case FileRWToolSettings frw: frw.PersonalAllowedExtensions = FileRwPersonalAllowedExtensions; frw.SharedAccessLevel = FileRwSharedAccessLevel; frw.SharedAllowedExtensions = FileRwSharedAllowedExtensions; frw.ProtectedPaths = FileRwProtectedPaths; break; } Result = ToolSettingsFactory.ToConfig(ToolName, SettingsObject) ?? new(); CloseRequested?.Invoke(); } [RelayCommand] private void Cancel() { Result = null; CloseRequested?.Invoke(); } }