Initial project

This commit is contained in:
Cody
2026-03-06 14:56:17 +08:00
parent 977b627b15
commit bf9e099747
1180 changed files with 50973 additions and 0 deletions

View File

@@ -0,0 +1,31 @@
import 'package:freezed_annotation/freezed_annotation.dart';
part 'api_error.freezed.dart';
/// API 统一错误类型Freezed 联合类型)
@freezed
class ApiError with _$ApiError implements Exception {
const factory ApiError.noNetworkConnection() = _NoNetworkConnection;
const factory ApiError.timeout() = _Timeout;
const factory ApiError.networkError(String message) = _NetworkError;
const factory ApiError.decodingError(String message) = _DecodingError;
const factory ApiError.apiError({
required int code,
required String message,
}) = _ApiError;
const factory ApiError.unknown(String? message) = _Unknown;
}
/// 错误类型扩展 - 提供用户可读的错误描述
extension ApiErrorExtension on ApiError {
String get displayMessage {
return when(
noNetworkConnection: () => 'No network connection',
timeout: () => 'Request timeout',
networkError: (message) => 'Network error: $message',
decodingError: (message) => 'Decoding error: $message',
apiError: (code, message) => message,
unknown: (message) => message ?? 'Unknown error',
);
}
}

View File

@@ -0,0 +1,11 @@
/// API 请求类型
enum ApiRequestType {
/// 普通请求(包含 token header
request,
/// 登录请求(不包含 token header
login,
/// 文件上传multipart不序列化 parameters
upload,
}

View File

@@ -0,0 +1,11 @@
/// HTTP 方法枚举
enum HttpMethod {
get('GET'),
post('POST'),
put('PUT'),
delete('DELETE'),
patch('PATCH');
final String value;
const HttpMethod(this.value);
}

View File

@@ -0,0 +1,18 @@
/// Domain Entity
/// - 表達「通知權限狀態」這個業務概念
/// - 穩定、可被 Facade 回傳
/// - 不要包含 JSON / platform / plugin
class NetworksSdkPermissionStatus {
final bool isGranted;
final bool isPermanentlyDenied;
final DateTime? grantedAt;
const NetworksSdkPermissionStatus({
required this.isGranted,
required this.isPermanentlyDenied,
this.grantedAt,
});
/// 純業務邏輯允許
bool get canRequestAgain => !isGranted && !isPermanentlyDenied;
}

View File

@@ -0,0 +1,14 @@
/// WebSocket 连接状态
enum SocketConnectionState {
/// 未连接
disconnected,
/// 连接中
connecting,
/// 已连接
connected,
/// 重连中(断线后自动重连)
reconnecting,
}

View File

@@ -0,0 +1,33 @@
import 'package:freezed_annotation/freezed_annotation.dart';
part 'socket_error.freezed.dart';
/// WebSocket 统一错误类型Freezed 联合类型)
@freezed
class SocketError with _$SocketError implements Exception {
const factory SocketError.connectionFailed(String message) =
_ConnectionFailed;
const factory SocketError.connectionTimeout() = _ConnectionTimeout;
const factory SocketError.disconnected({String? reason}) = _Disconnected;
const factory SocketError.pingTimeout() = _PingTimeout;
const factory SocketError.networkUnavailable() = _NetworkUnavailable;
const factory SocketError.invalidURL(String url) = _InvalidURL;
const factory SocketError.sendFailed(String message) = _SendFailed;
const factory SocketError.unknown(String? message) = _Unknown;
}
/// 错误类型扩展 — 提供用户可读的错误描述
extension SocketErrorExtension on SocketError {
String get displayMessage {
return when(
connectionFailed: (message) => 'Connection failed: $message',
connectionTimeout: () => 'Connection timeout',
disconnected: (reason) => reason ?? 'Disconnected',
pingTimeout: () => 'Ping timeout',
networkUnavailable: () => 'Network unavailable',
invalidURL: (url) => 'Invalid URL: $url',
sendFailed: (message) => 'Send failed: $message',
unknown: (message) => message ?? 'Unknown error',
);
}
}

View File

@@ -0,0 +1,49 @@
import 'package:networks_sdk/src/domain/entities/socket_connection_state.dart';
import 'package:networks_sdk/src/domain/entities/socket_error.dart';
import 'package:networks_sdk/src/presentation/wiring/socket_config.dart';
/// Messaging Repository Interface (Domain)
abstract class NetworksMessagingRepository {
/// Initialize with config
void initialize(SocketConfig config);
/// Connect to messaging server
Future<bool> connect(String url, {String? token});
/// Disconnect from server
Future<void> disconnect();
/// Check if connected
bool get isConnected;
/// Current connection state
SocketConnectionState get connectionState;
/// Send a JSON message
Future<bool> send(Map<String, dynamic> message);
/// Send a raw string message
Future<bool> sendString(String message);
/// Stream of incoming parsed JSON messages
Stream<Map<String, dynamic>> get messageStream;
/// Stream of raw string messages
Stream<String> get rawMessageStream;
/// Stream of connection state changes
Stream<SocketConnectionState> get connectionStateStream;
/// Stream of errors
Stream<SocketError> get errorStream;
/// Called when app enters foreground
void onEnterForeground();
/// Called when app enters background
void onEnterBackground();
/// Dispose all resources
Future<void> dispose();
}

View File

@@ -0,0 +1,12 @@
// Repository InterfaceDomain
import 'package:networks_sdk/src/data/dto/api_requestable.dart';
import 'package:networks_sdk/src/presentation/wiring/api_config.dart';
abstract class NetworksSdkRepository {
Future<String?> platformVersion();
void initialize(ApiConfig apiConfig);
Future<T?> executeRequest<T>(ApiRequestable<T> request);
}

View File

@@ -0,0 +1,15 @@
//UseCase
import '../repositories/networks_sdk_repository.dart';
class PlatformVersion
{
final NetworksSdkRepository _repository;
const PlatformVersion(this._repository);
Future<String?> call() {
return _repository.platformVersion();
}
}