import 'dart:convert'; import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; import 'package:shared_preferences/shared_preferences.dart'; import 'package:uid/uid.dart'; import 'package:path_provider/path_provider.dart'; import 'dart:io'; class SettingsProvider extends ChangeNotifier { String _OPENAI_API_KEY = ""; String get openAIApiKey => _OPENAI_API_KEY; List _feeds = [ // Major Business News Feed( title: "Business Insider", url: "https://feeds.businessinsider.com/custom/all" ), Feed( title: "BBC Business", url: "https://feeds.bbci.co.uk/news/business/rss.xml" ), Feed( title: "Reuters Business", url: "https://www.reutersagency.com/feed/?taxonomy=best-topics&post_type=best" ), Feed( title: "Financial Times", url: "https://www.ft.com/?format=rss" ), Feed( title: "Bloomberg", url: "https://feeds.bloomberg.com/markets/news.rss" ), // Market-Specific Feed( title: "MarketWatch", url: "https://feeds.marketwatch.com/marketwatch/topstories/" ), Feed( title: "Seeking Alpha", url: "https://seekingalpha.com/feed.xml" ), Feed( title: "Yahoo Finance", url: "https://finance.yahoo.com/news/rssindex" ), Feed( title: "CNBC", url: "https://www.cnbc.com/id/100003114/device/rss/rss.html" ), Feed( title: "The Wall Street Journal", url: "https://feeds.a.dj.com/rss/RSSMarketsMain.xml" ), // Tech Business Feed( title: "TechCrunch", url: "https://techcrunch.com/feed/" ), Feed( title: "The Verge", url: "https://www.theverge.com/rss/index.xml" ), Feed( title: "Ars Technica", url: "https://feeds.arstechnica.com/arstechnica/index" ), // Company News Feed( title: "Fortune", url: "https://fortune.com/feed" ), Feed( title: "Forbes Business", url: "https://www.forbes.com/business/feed/" ), Feed( title: "Inc Magazine", url: "https://www.inc.com/rss" ), // Industry-Specific Feed( title: "Retail Dive", url: "https://www.retaildive.com/feeds/news/" ), Feed( title: "Manufacturing Dive", url: "https://www.manufacturingdive.com/feeds/news/" ), Feed( title: "Banking Dive", url: "https://www.bankingdive.com/feeds/news/" ), // Economic News Feed( title: "The Economist", url: "https://www.economist.com/finance-and-economics/rss.xml" ), Feed( title: "Federal Reserve News", url: "https://www.federalreserve.gov/feeds/press_all.xml" ), ]; // List of rss feed URLs List get feeds => List.unmodifiable(_feeds); late String _applicationStorageLocation; String get applicationStorageLocation => _applicationStorageLocation; static SettingsProvider of(BuildContext context) { return Provider.of(context, listen: false); } Future load() async { // get documents directory dynamicly final Directory appDocDir = await getApplicationDocumentsDirectory(); _applicationStorageLocation = appDocDir.path; SharedPreferences prefs = await SharedPreferences.getInstance(); _OPENAI_API_KEY = prefs.getString('openai_api_key') ?? _OPENAI_API_KEY; List? feedStrings = prefs.getStringList('feeds'); if (feedStrings != null) { _feeds = feedStrings.map((fStr) { try { return Feed.fromJson(jsonDecode(fStr)); } catch (e) { // old format, parse manually Map json = {}; fStr.substring(1, fStr.length - 1).split(', ').forEach((pair) { List keyValue = pair.split(': '); String key = keyValue[0]; String value = keyValue[1]; // convert bool strings to actual bools if (value == 'true') { json[key] = true; } else if (value == 'false') { json[key] = false; } else { json[key] = value; } }); return Feed.fromJson(json); } }).toList(); } _applicationStorageLocation = prefs.getString('application_storage_location') ?? applicationStorageLocation; notifyListeners(); } Future save() async { SharedPreferences prefs = await SharedPreferences.getInstance(); await prefs.setString('openai_api_key', _OPENAI_API_KEY); await prefs.setStringList('feeds', _feeds.map((f) => jsonEncode(f.toJson())).toList()); await prefs.setString('application_storage_location', _applicationStorageLocation); } void setOpenAIApiKey(String key) { _OPENAI_API_KEY = key; save(); notifyListeners(); } void addFeed(Feed feed) { _feeds.add(feed); save(); notifyListeners(); } Feed updateFeed(int id, {String? title, String? url, bool? enabled}) { for (int i = 0; i < _feeds.length; i++) { if (_feeds[i].id == id) { Feed updatedFeed = Feed( url: url ?? _feeds[i].url, title: title ?? _feeds[i].title, enabled: enabled ?? _feeds[i].enabled, ); _feeds[i] = updatedFeed; save(); notifyListeners(); return updatedFeed; } } throw Exception("Feed with id $id not found"); } void removeFeed(Feed feed) { _feeds.removeWhere((f) => f.url == feed.url); save(); notifyListeners(); } void setApplicationStorageLocation(String path) { _applicationStorageLocation = path; save(); notifyListeners(); } } class Feed { final String url; final String title; final bool enabled; Feed({required this.url, required this.title, this.enabled = true}); Feed.fromJson(Map json) : url = json['url'], title = json['title'], enabled = json['enabled'] ?? true; Map toJson() => { 'url': url, 'title': title, 'enabled': enabled, }; int get id { return url.hashCode ^ title.hashCode; } }