235 lines
6.1 KiB
Dart
235 lines
6.1 KiB
Dart
|
|
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<Feed> _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<Feed> get feeds => List.unmodifiable(_feeds);
|
|
|
|
late String _applicationStorageLocation;
|
|
String get applicationStorageLocation => _applicationStorageLocation;
|
|
|
|
static SettingsProvider of(BuildContext context) {
|
|
return Provider.of<SettingsProvider>(context, listen: false);
|
|
}
|
|
|
|
Future<void> 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<String>? feedStrings = prefs.getStringList('feeds');
|
|
if (feedStrings != null) {
|
|
_feeds = feedStrings.map((fStr) {
|
|
try {
|
|
return Feed.fromJson(jsonDecode(fStr));
|
|
} catch (e) {
|
|
// old format, parse manually
|
|
Map<String, dynamic> json = {};
|
|
fStr.substring(1, fStr.length - 1).split(', ').forEach((pair) {
|
|
List<String> 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<void> 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<String, dynamic> json)
|
|
: url = json['url'],
|
|
title = json['title'],
|
|
enabled = json['enabled'] ?? true;
|
|
|
|
Map<String, dynamic> toJson() => {
|
|
'url': url,
|
|
'title': title,
|
|
'enabled': enabled,
|
|
};
|
|
|
|
int get id {
|
|
return url.hashCode ^ title.hashCode;
|
|
}
|
|
} |