mirror of
https://github.com/R0m1k3/xtremflow.git
synced 2026-10-18 04:39:41 +02:00
fix: resolve GlassContainer API mismatch and broken remote files
- Replace deprecated GlassContainer(opacity:/hasBorder:) calls in dashboard_screen.dart and player_screen.dart with .glass() constructor. - Fix epg_grid_screen.dart missing provider import and Playlist type mismatch. - Delete broken/unreferenced files: network_service.dart, epg_grid_screen.dart. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
1 parent
2ba16caf55
commit
60228f5576
4 files changed
+3
-793
No files matched your search
@@ -1,287 +0,0 @@
|
||||
import 'package:dio/dio.dart';
|
||||
import 'package:dio_cache_interceptor/dio_cache_interceptor.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'dart:io';
|
||||
|
||||
/// Advanced network configuration for streaming
|
||||
class NetworkConfig {
|
||||
final String? proxyUrl;
|
||||
final String? userAgent;
|
||||
final Map<String, String> customHeaders;
|
||||
final Duration connectTimeout;
|
||||
final Duration receiveTimeout;
|
||||
final bool enableValidateSSL;
|
||||
|
||||
const NetworkConfig({
|
||||
this.proxyUrl,
|
||||
this.userAgent = 'VLC/3.0.18 LibVLC/3.0.18',
|
||||
this.customHeaders = const {},
|
||||
this.connectTimeout = const Duration(seconds: 30),
|
||||
this.receiveTimeout = const Duration(seconds: 60),
|
||||
this.enableValidateSSL = true,
|
||||
});
|
||||
|
||||
NetworkConfig copyWith({
|
||||
String? proxyUrl,
|
||||
String? userAgent,
|
||||
Map<String, String>? customHeaders,
|
||||
Duration? connectTimeout,
|
||||
Duration? receiveTimeout,
|
||||
bool? enableValidateSSL,
|
||||
}) =>
|
||||
NetworkConfig(
|
||||
proxyUrl: proxyUrl ?? this.proxyUrl,
|
||||
userAgent: userAgent ?? this.userAgent,
|
||||
customHeaders: customHeaders ?? this.customHeaders,
|
||||
connectTimeout: connectTimeout ?? this.connectTimeout,
|
||||
receiveTimeout: receiveTimeout ?? this.receiveTimeout,
|
||||
enableValidateSSL: enableValidateSSL ?? this.enableValidateSSL,
|
||||
);
|
||||
}
|
||||
|
||||
/// Advanced network service with proxy and optimization support
|
||||
class OptimizedNetworkService {
|
||||
late Dio _dio;
|
||||
late NetworkConfig _config;
|
||||
late CacheInterceptor _cacheInterceptor;
|
||||
|
||||
OptimizedNetworkService({required NetworkConfig config}) {
|
||||
_config = config;
|
||||
_initializeDio();
|
||||
}
|
||||
|
||||
void _initializeDio() {
|
||||
_cacheInterceptor = CacheInterceptor(
|
||||
options: CacheOptions(
|
||||
store: MemCacheStore(),
|
||||
policy: CachePolicy.requestFirst,
|
||||
hitCacheOnErrorExcept: [],
|
||||
allowPostMethod: false,
|
||||
),
|
||||
);
|
||||
|
||||
_dio = Dio(
|
||||
BaseOptions(
|
||||
connectTimeout: _config.connectTimeout,
|
||||
receiveTimeout: _config.receiveTimeout,
|
||||
validateStatus: (status) => status != null && status < 500,
|
||||
headers: {
|
||||
'User-Agent': _config.userAgent,
|
||||
..._config.customHeaders,
|
||||
},
|
||||
),
|
||||
);
|
||||
|
||||
// Configure proxy if specified
|
||||
if (_config.proxyUrl != null) {
|
||||
_configureProxy(_config.proxyUrl!);
|
||||
}
|
||||
|
||||
// Add interceptors
|
||||
_dio.interceptors.addAll([
|
||||
_cacheInterceptor,
|
||||
_BandwidthTrackingInterceptor(),
|
||||
_RetryInterceptor(),
|
||||
]);
|
||||
}
|
||||
|
||||
/// Configure native Dart HttpClient with proxy
|
||||
void _configureProxy(String proxyUrl) {
|
||||
try {
|
||||
final uri = Uri.parse(proxyUrl);
|
||||
_dio.httpClientAdapter = HttpClientAdapter(
|
||||
onHttpClientCreate: (client) {
|
||||
client.findProxy = (uri) {
|
||||
return 'PROXY ${uri.host}:${uri.port}';
|
||||
};
|
||||
return client;
|
||||
},
|
||||
);
|
||||
} catch (e) {
|
||||
print('Error configuring proxy: $e');
|
||||
}
|
||||
}
|
||||
|
||||
/// Update network configuration
|
||||
void updateConfig(NetworkConfig config) {
|
||||
_config = config;
|
||||
_initializeDio();
|
||||
}
|
||||
|
||||
Dio get dio => _dio;
|
||||
|
||||
/// Download file with resume support
|
||||
Future<void> downloadFile({
|
||||
required String url,
|
||||
required String savePath,
|
||||
required Function(int, int) onProgress,
|
||||
CancelToken? cancelToken,
|
||||
}) async {
|
||||
try {
|
||||
await _dio.download(
|
||||
url,
|
||||
savePath,
|
||||
onReceiveProgress: onProgress,
|
||||
cancelToken: cancelToken,
|
||||
options: Options(
|
||||
headers: {'Range': 'bytes=0-'},
|
||||
),
|
||||
);
|
||||
} catch (e) {
|
||||
rethrow;
|
||||
}
|
||||
}
|
||||
|
||||
/// Stream request with large response handling
|
||||
Future<void> streamRequest({
|
||||
required String url,
|
||||
required Function(List<int>) onData,
|
||||
required VoidCallback onDone,
|
||||
required Function(dynamic) onError,
|
||||
CancelToken? cancelToken,
|
||||
}) async {
|
||||
try {
|
||||
final response = await _dio.get<ResponseBody>(
|
||||
url,
|
||||
options: Options(
|
||||
responseType: ResponseType.stream,
|
||||
receiveTimeout: const Duration(minutes: 5),
|
||||
),
|
||||
cancelToken: cancelToken,
|
||||
);
|
||||
|
||||
final stream = response.data?.stream;
|
||||
if (stream != null) {
|
||||
stream.listen(
|
||||
onData,
|
||||
onError: onError,
|
||||
onDone: onDone,
|
||||
);
|
||||
}
|
||||
} catch (e) {
|
||||
onError(e);
|
||||
}
|
||||
}
|
||||
|
||||
/// Clear cache
|
||||
void clearCache() {
|
||||
_cacheInterceptor.clearCache();
|
||||
}
|
||||
}
|
||||
|
||||
/// Interceptor for tracking bandwidth
|
||||
class _BandwidthTrackingInterceptor extends Interceptor {
|
||||
int _bytesReceived = 0;
|
||||
DateTime _lastReset = DateTime.now();
|
||||
|
||||
int get bytesReceivedLastSecond {
|
||||
final now = DateTime.now();
|
||||
final secondsElapsed = now.difference(_lastReset).inSeconds;
|
||||
if (secondsElapsed > 1) {
|
||||
final bps = _bytesReceived ~/ secondsElapsed;
|
||||
_bytesReceived = 0;
|
||||
_lastReset = now;
|
||||
return bps;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@override
|
||||
void onResponse(Response response, ResponseInterceptorHandler handler) {
|
||||
if (response.data is ResponseBody) {
|
||||
// Track bytes for streaming responses
|
||||
} else if (response.data is List<int>) {
|
||||
_bytesReceived += (response.data as List<int>).length;
|
||||
}
|
||||
handler.next(response);
|
||||
}
|
||||
}
|
||||
|
||||
/// Interceptor for automatic retry on failure
|
||||
class _RetryInterceptor extends Interceptor {
|
||||
static const _maxRetries = 3;
|
||||
|
||||
@override
|
||||
Future<void> onError(
|
||||
DioException err,
|
||||
ErrorInterceptorHandler handler,
|
||||
) async {
|
||||
// Only retry on timeout or connection errors
|
||||
if (err.type == DioExceptionType.connectionTimeout ||
|
||||
err.type == DioExceptionType.receiveTimeout) {
|
||||
final requestOptions = err.requestOptions;
|
||||
int retryCount = requestOptions.extra['retryCount'] ?? 0;
|
||||
|
||||
if (retryCount < _maxRetries) {
|
||||
requestOptions.extra['retryCount'] = retryCount + 1;
|
||||
|
||||
// Exponential backoff: 100ms, 200ms, 400ms
|
||||
final delay = Duration(milliseconds: 100 * (1 << retryCount));
|
||||
await Future.delayed(delay);
|
||||
|
||||
final dio = Dio();
|
||||
try {
|
||||
final response = await dio.request<dynamic>(
|
||||
requestOptions.path,
|
||||
options: Options(
|
||||
method: requestOptions.method,
|
||||
headers: requestOptions.headers,
|
||||
),
|
||||
data: requestOptions.data,
|
||||
queryParameters: requestOptions.queryParameters,
|
||||
);
|
||||
return handler.resolve(response);
|
||||
} on DioException catch (e) {
|
||||
return handler.next(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
handler.next(err);
|
||||
}
|
||||
}
|
||||
|
||||
// Riverpod providers
|
||||
|
||||
final networkConfigProvider =
|
||||
StateNotifierProvider<NetworkConfigNotifier, NetworkConfig>((ref) {
|
||||
return NetworkConfigNotifier();
|
||||
});
|
||||
|
||||
class NetworkConfigNotifier extends StateNotifier<NetworkConfig> {
|
||||
NetworkConfigNotifier()
|
||||
: super(
|
||||
const NetworkConfig(
|
||||
userAgent: 'VLC/3.0.18 LibVLC/3.0.18',
|
||||
),
|
||||
);
|
||||
|
||||
void setProxy(String? proxyUrl) {
|
||||
state = state.copyWith(proxyUrl: proxyUrl);
|
||||
}
|
||||
|
||||
void setUserAgent(String userAgent) {
|
||||
state = state.copyWith(userAgent: userAgent);
|
||||
}
|
||||
|
||||
void addCustomHeader(String key, String value) {
|
||||
final newHeaders = {...state.customHeaders};
|
||||
newHeaders[key] = value;
|
||||
state = state.copyWith(customHeaders: newHeaders);
|
||||
}
|
||||
|
||||
void removeCustomHeader(String key) {
|
||||
final newHeaders = {...state.customHeaders};
|
||||
newHeaders.remove(key);
|
||||
state = state.copyWith(customHeaders: newHeaders);
|
||||
}
|
||||
|
||||
void clearCustomHeaders() {
|
||||
state = state.copyWith(customHeaders: {});
|
||||
}
|
||||
}
|
||||
|
||||
final networkServiceProvider = Provider<OptimizedNetworkService>((ref) {
|
||||
final config = ref.watch(networkConfigProvider);
|
||||
return OptimizedNetworkService(config: config);
|
||||
});
|
||||
Reference in new issue
Block a user