feat: 请求数据和配置

This commit is contained in:
phoenix--zhang 2026-07-06 15:21:29 +08:00
parent 557f900187
commit 9b0fe51fa4
21 changed files with 1026 additions and 60 deletions

BIN
assets/main/launcher.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 MiB

View File

@ -39,17 +39,6 @@ class AppService {
//
_dio.interceptors.add(NyNetworkIntercept());
//
// if (!kReleaseMode) {
// _dio.interceptors.add(TalkerDioLogger(
// settings: TalkerDioLoggerSettings(
// printRequestHeaders: true,
// printRequestData: true,
// printResponseData: true,
// printResponseHeaders: false,
// ),
// ));
// }
}
///
@ -279,7 +268,6 @@ class ApiRequest {
throw Exception("retry failed (unreachable)");
}
// ============ ============
static HttpResult<T> _handleError<T>(DioException e) {
final Response? resp = e.response;

View File

@ -2,7 +2,7 @@
// https://api-glimzodf.glimzodf.com/glimzodf/
class ApiString {
static const String baseUrl = "https://api-glimzodf.glimzodf.com/";
static const String baseUrl = "https://api-glimzodf.glimzodf.com/glimzodf";
static const String appName = 'Novyronst';

View File

@ -1,7 +1,7 @@
import 'dart:convert';
import 'package:dio/dio.dart';
import 'package:flutter/foundation.dart';
import 'package:logger/logger.dart';
import 'package:novyronst/common/help/help_log.dart';
import 'package:novyronst/common/help/help_time.dart';
import 'package:novyronst/common/help/help_token.dart';
@ -11,19 +11,18 @@ import '../help/help_encrypt.dart';
///
class NyNetworkIntercept extends Interceptor {
final bool enableLog = !kReleaseMode;
final Logger _logger = Logger();
@override
Future<void> onRequest(RequestOptions options, RequestInterceptorHandler handler) async {
//
await _addRequestHeaders(options);
//
_logInfo("🔶 REQUEST [${options.method.toUpperCase()}] ${options.uri}");
_logDebug("Headers: ${options.headers}");
HelpLog.print("🔶 REQUEST [${options.method.toUpperCase()}] ${options.uri}");
HelpLog.print("Headers: ${options.headers}");
if (options.data != null) {
_logDebug("Payload: ${options.data}");
HelpLog.print("Payload: ${options.data}");
}
handler.next(options);
@ -31,7 +30,7 @@ class NyNetworkIntercept extends Interceptor {
@override
void onResponse(Response response, ResponseInterceptorHandler handler) {
_logInfo("🟢 RESPONSE [${response.statusCode}] ${response.requestOptions.uri}");
HelpLog.print("🟢 RESPONSE [${response.statusCode}] ${response.requestOptions.uri}");
// _logDebug("Body: ${response.data}");
// 401 / 402 Token
@ -56,7 +55,7 @@ class NyNetworkIntercept extends Interceptor {
final deStr = HelpEncrypt.deStr(response.data);
response.data = jsonDecode(deStr);
} catch (e) {
_logError("解密失败: $e");
HelpLog.print("解密失败: $e");
}
}
@ -65,14 +64,13 @@ class NyNetworkIntercept extends Interceptor {
@override
void onError(DioException err, ErrorInterceptorHandler handler) {
_logError("🔴 Error: ${err.message}");
HelpLog.print("🔴 Error: ${err.message}", tag: 'in onError');
handler.next(err);
}
// ============ ============
Future<void> _addRequestHeaders(RequestOptions options) async {
// security: false
if (!kReleaseMode) {
options.headers['security'] = 'false';
}
@ -80,7 +78,6 @@ class NyNetworkIntercept extends Interceptor {
// Token
final tokenManager = HelpToken();
final token = tokenManager.get();
// print('查看token: $token');
if (token.isNotEmpty) {
options.headers['Authorization'] = 'Bearer $token';
}
@ -104,7 +101,6 @@ class NyNetworkIntercept extends Interceptor {
'device-gaid': '',
});
// prevToken
await _handleOldToken(options);
}
@ -117,25 +113,11 @@ class NyNetworkIntercept extends Interceptor {
options.headers['Authorization'] = prevToken.toString();
}
}
} catch (_) {
// JSON
}
} catch (_) {}
}
void _logInfo(String message) {
if (enableLog) _logger.i(message);
}
void _logDebug(String message) {
if (enableLog) _logger.d('💡 $message');
}
void _logError(String message) {
if (enableLog) _logger.e(message);
}
void _handleError(dynamic e, bool error) {
_logError("🔴 Error: $e");
//
HelpLog.print("🔴 Error: $e", tag: 'in ---- _handleError');
}
}

View File

@ -2,6 +2,7 @@
import 'package:novyronst/common/api/api_request.dart';
import 'package:novyronst/common/api/api_string.dart';
import 'package:novyronst/common/help/help_log.dart';
import 'package:novyronst/common/help/help_token.dart';
import 'package:novyronst/common/model/novyronst_user.dart';
import 'package:novyronst/common/model/register_model.dart';
@ -38,4 +39,65 @@ class UserRequest {
return null;
});
}
static Future eventCreateHis({
required String shortPlayId,
required String videoId
}) {
// {"short_play_id": shortPlayId, "video_id": videoId}
Map<String, dynamic> params = {"short_play_id": shortPlayId, "video_id": videoId};
return ApiRequest.post(ApiStringUser.eventCreateHistory, data: params).then((value) {
HelpLog.print(value.data, tag: "eventCreateHis");
});
}
static Future eventEnterApp() {
return ApiRequest.post(ApiStringUser.eventUserEnterApp).then((value) {});
}
static Future<bool> eventOnline({String? oldToken}) {
String token = HelpToken().get();
if (token == '') return Future<bool>.value(false);
final body = <String, dynamic>{};
if (oldToken != null) body['token'] = oldToken;
return ApiRequest.post(ApiStringUser.eventUserOnline, data: body).then((value) {
return value.isSuccess;
});
}
static Future<bool> eventOLeaveApp({String? oldToken}) {
String token = HelpToken().get();
if (token == '') return Future<bool>.value(false);
final body = <String, dynamic>{};
if (oldToken != null) body['token'] = oldToken;
return ApiRequest.post(ApiStringUser.eventUserLeaveApp, data: body).then((value) {
return value.isSuccess;
});
}
//
static Future eventPlaySeconds({
required int shortPlayId,
required int videoId,
required int seconds,
}) {
return ApiRequest.post(ApiStringUser.eventPlaySeconds, data: {
"short_play_id": shortPlayId,
"video_id": videoId,
"play_seconds": seconds,
}).then((value) {});
}
//
static Future eventWatchTime({
required int shortPlayId,
required int seconds,
}) {
return ApiRequest.post(ApiStringUser.eventWatchTime, data: {
"short_play_id": shortPlayId,
//
"request_id": DateTime.now().millisecondsSinceEpoch,
"duration": seconds,
}).then((value) {});
}
}

View File

@ -0,0 +1,181 @@
import 'package:novyronst/common/api/api_request.dart';
import 'package:novyronst/common/api/api_string.dart';
import 'package:novyronst/common/help/help_log.dart';
import 'package:novyronst/common/model/ny_category_model.dart';
import 'package:novyronst/common/model/ny_drama_model.dart';
import 'package:novyronst/common/model/ny_home_model.dart';
import '../model/ny_detail_model.dart';
class VideoRequest {
static Future<List<NyHomeModel>> getHomeData() {
return ApiRequest.get(ApiStringVideo.getHomeModules).then((value) {
if (value.isSuccess) {
List? list = value.data['data']['list'];
List<NyHomeModel> homeList = [];
if (list != null) {
homeList = list.map((e) => NyHomeModel.fromJson(e)).toList();
}
return homeList;
}
return [];
});
}
static Future<List<NyCategoryModel>> getCategoriesList() {
return ApiRequest.get(ApiStringVideo.getCategoriesList).then((value) {
// SkyLog.print('vvvvv: ${value.data}');
if (!value.isSuccess) return [];
Map<String, dynamic> data = value.data['data'];
List? list = data['list'];
List<NyCategoryModel> categoryList = [];
if (list != null) {
// id 28 ,
categoryList = list.map((e) => NyCategoryModel.fromJson(e)).toList();
categoryList.removeWhere((element) => element.id == 28);
categoryList.removeWhere((element) => element.name.length >= 10);
}
return categoryList;
});
}
static Future<List<NyDramaModel>> getCategoriesDetail({
required int categoryId,
int page = 1,
int pageSize = 20,
}) {
return ApiRequest.fetchPage<NyDramaModel>(
ApiStringVideo.getCategoriesDetail,
page: page,
pageSize: pageSize,
extraParams: {'category_id': categoryId},
fromJson: (json) => NyDramaModel.fromJson(json),
);
}
// getSearchHots
static Future<List<NyDramaModel>> getSearchHots() {
return ApiRequest.get(ApiStringVideo.getSearchHots).then((value) {
if (value.isSuccess) {
HelpLog.print('getSearchHots: ${value.data}');
List list = parseDataForList(value.data);
return list.map((e) => NyDramaModel.fromJson(e)).toList();
}
return [];
});
}
// search
static Future<List<NyDramaModel>> search({required String keyword}) {
return ApiRequest.get(ApiStringVideo.getSearch, queryParameters: {
'search': keyword,
}).then((value) {
if (value.isSuccess) {
HelpLog.print('getSearchHots: ${value.data}');
List list = parseDataForList(value.data);
return list.map((e) => NyDramaModel.fromJson(e)).toList();
}
return [];
});
}
//getCollections
static Future<List<NyDramaModel>> getCollections({
int page = 1,
int pageSize = 10,
}) {
Map<String, dynamic> params = _setPage(page: page, pageSize: pageSize);
return ApiRequest.get(
ApiStringVideo.getCollections,
queryParameters: params,
).then((value) {
if (value.isSuccess) {
HelpLog.print('getCollections: ${value.data}');
List list = parseDataForList(value.data);
return list.map((e) => NyDramaModel.fromJson(e)).toList();
}
return [];
});
}
// getHistory
static Future<List<NyDramaModel>> getHistory({
int page = 1,
int pageSize = 10,
}) {
Map<String, dynamic> params = _setPage(page: page, pageSize: pageSize);
return ApiRequest.get(
ApiStringVideo.getHistories,
queryParameters: params,
).then((value) {
if (value.isSuccess) {
HelpLog.print('getHistory: ${value.data}');
List list = parseDataForList(value.data);
return list.map((e) => NyDramaModel.fromJson(e)).toList();
}
return [];
});
}
// getVideoDetail
static Future<NyDetailModel?> getVideoDetail({
required int shortPlayId,
required int shortPlayVideoId,
}) {
Map<String, dynamic> params = {};
params['short_play_id'] = shortPlayId;
params['short_play_video_id'] = shortPlayVideoId;
return ApiRequest.get(
ApiStringVideo.getVideoDetail,
queryParameters: params,
).then((value) {
if (value.isSuccess) {
HelpLog.print('getVideoDetail: ${value.data['data']}');
return NyDetailModel.fromJson(value.data['data']);
}
return null;
});
}
// collect
static Future<bool> collect({
required int shortPlayId,
required int videoId,
}) {
Map<String, dynamic> params = {};
params['short_play_id'] = shortPlayId;
params['video_id'] = videoId;
return ApiRequest.post(ApiStringVideo.collect, data: params).then((value) {
HelpLog.print('collecttttt: ${value.data}');
if (value.isSuccess) {}
return value.isSuccess;
});
}
// cancelCollect
static Future<bool> cancelCollect({required int shortPlayId}) {
Map<String, dynamic> params = {};
params['short_play_id'] = shortPlayId;
return ApiRequest.post(ApiStringVideo.cancelCollect, data: params).then((
value,
) {
HelpLog.print('cancelCollectttt: ${value.data}');
if (value.isSuccess) {}
return value.isSuccess;
});
}
static Map<String, dynamic> _setPage({int page = 1, int pageSize = 10}) {
return {'current_page': page, 'page_size': pageSize};
}
static List parseDataForList(Map<String, dynamic> data) {
Map<String, dynamic> map = data['data'];
List? listData = map['list'];
return listData ?? [];
}
}

View File

@ -15,6 +15,7 @@ class ConstImage {
static const String btCollectSel = "assets/main/bt_collect_seled.png";
static const String btMineSel = "assets/main/bt_mine_seled.png";
static const String spaceImg = "assets/main/space_img.png";
static const String launcher = "assets/main/launcher.png";
/// imgs
static const String searchBg = "assets/imgs/search_bg.png";

View File

@ -0,0 +1,35 @@
import 'package:get/get.dart';
import 'package:novyronst/pages/play/pages/laucher_page.dart';
class HelpRouters {
static const String launcher = '/launcher';
}
class HelpPages {
static const initial = HelpRouters.launcher;
static final List<GetPage> routes = [
routePage(name: HelpRouters.launcher, page: ()=> LauncherPage())
];
}
GetPage routePage({
required String name,
required GetPageBuilder page,
Bindings? binding,
Transition transition = Transition.rightToLeft,
Duration transitionDuration = const Duration(milliseconds: 300),
CustomTransition? customTransition,
bool popGesture = true, // Allow iOS swipe-back gesture by default
}) {
return GetPage(
name: name,
page: page,
binding: binding,
transition: transition,
transitionDuration: transitionDuration,
customTransition: customTransition,
popGesture: popGesture, // Pass through to GetPage
);
}

View File

@ -65,7 +65,6 @@ class HelpToken {
}
}
// ============ 便 ============
/// Token
bool get isEmpty => get().isEmpty;
@ -82,7 +81,6 @@ class HelpToken {
return null;
}
// ============ ============
///
void saveUserInfo(Map<String, dynamic> userInfo) {
@ -107,12 +105,9 @@ class HelpToken {
return null;
}
// ============ ============
String? _getFromStorage(String key) {
try {
// 使 SharedPreferences SharedPreferences
// 使
//
return _getFromStorageSync(key);
} catch (e) {
@ -121,13 +116,9 @@ class HelpToken {
}
}
// SharedPreferences
String? _getFromStorageSync(String key) {
// SharedPreferences 使
// main init()
try {
// null
// 使
return null;
} catch (_) {
return null;

View File

@ -0,0 +1,24 @@
import 'package:novyronst/common/model/parse_model.dart';
class NyCategoryModel {
final int id;
final String name;
const NyCategoryModel({required this.id, required this.name});
factory NyCategoryModel.fromJson(Map<String, dynamic> json) {
return NyCategoryModel(
id: parseInt(json['id']),
name: parseString(json['name']),
);
}
Map<String, dynamic> toJson() {
return {'id': id, 'name': name};
}
NyCategoryModel copyWith({int? id, String? name}) {
return NyCategoryModel(id: id ?? this.id, name: name ?? this.name);
}
}

View File

@ -0,0 +1,113 @@
import 'package:novyronst/common/model/ny_drama_model.dart';
import 'package:novyronst/common/model/ny_episode_model.dart';
import 'package:novyronst/common/model/parse_model.dart';
class NyDetailModel {
final NyDramaModel? videoInfo;
final NyDramaModel? shortPlayInfo;
final List<NyEpisodeModel> episodeList;
final String? businessModel;
bool? isCollect;
final bool? showShareCoin;
final int? shareCoin;
final int? revolution;
final String? userLevel;
final int? jumpType;
final int? jumpShortPlayId;
final List<int>? checkPoint;
NyDetailModel({
required this.videoInfo,
this.shortPlayInfo,
required this.episodeList,
this.businessModel,
this.isCollect,
this.showShareCoin,
this.shareCoin,
this.revolution,
this.userLevel,
this.jumpType,
this.jumpShortPlayId,
this.checkPoint,
});
factory NyDetailModel.fromJson(Map<String, dynamic> json) {
return NyDetailModel(
videoInfo: parseMap(json['video_info']) == null
? null
: NyDramaModel.fromJson(parseMap(json['video_info'])!),
shortPlayInfo: parseMap(json['shortPlayInfo']) == null
? null
: NyDramaModel.fromJson(parseMap(json['shortPlayInfo'])!),
episodeList: parseModelList(json['episodeList'], NyEpisodeModel.fromJson),
businessModel: json['business_model'] as String?,
isCollect: json['is_collect'] == null
? null
: parseBool(json['is_collect']),
showShareCoin: json['show_share_coin'] == null
? null
: parseBool(json['show_share_coin']),
shareCoin: json['share_coin'] == null
? null
: parseInt(json['share_coin']),
revolution: json['revolution'] == null
? null
: parseInt(json['revolution']),
userLevel: json['user_level'] as String?,
jumpType: json['jump_type'] == null ? null : parseInt(json['jump_type']),
jumpShortPlayId: json['jump_short_play_id'] == null
? null
: parseInt(json['jump_short_play_id']),
checkPoint: parseIntList(json['check_point']),
);
}
Map<String, dynamic> toJson() {
return {
'video_info': videoInfo?.toJson(),
'shortPlayInfo': shortPlayInfo?.toJson(),
'episodeList': episodeList.map((item) => item.toJson()).toList(),
'business_model': businessModel,
'is_collect': isCollect,
'show_share_coin': showShareCoin,
'share_coin': shareCoin,
'revolution': revolution,
'user_level': userLevel,
'jump_type': jumpType,
'jump_short_play_id': jumpShortPlayId,
'check_point': checkPoint,
};
}
NyDetailModel copyWith({
NyDramaModel? videoInfo,
NyDramaModel? shortPlayInfo,
List<NyEpisodeModel>? episodeList,
String? businessModel,
bool? isCollect,
bool? showShareCoin,
int? shareCoin,
int? revolution,
String? userLevel,
int? jumpType,
int? jumpShortPlayId,
List<int>? checkPoint,
}) {
return NyDetailModel(
videoInfo: videoInfo ?? this.videoInfo,
shortPlayInfo: shortPlayInfo ?? this.shortPlayInfo,
episodeList: episodeList ?? this.episodeList,
businessModel: businessModel ?? this.businessModel,
isCollect: isCollect ?? this.isCollect,
showShareCoin: showShareCoin ?? this.showShareCoin,
shareCoin: shareCoin ?? this.shareCoin,
revolution: revolution ?? this.revolution,
userLevel: userLevel ?? this.userLevel,
jumpType: jumpType ?? this.jumpType,
jumpShortPlayId: jumpShortPlayId ?? this.jumpShortPlayId,
checkPoint: checkPoint ?? this.checkPoint,
);
}
}

View File

@ -0,0 +1,185 @@
import 'package:novyronst/common/model/parse_model.dart';
import 'ny_category_model.dart';
class NyDramaModel {
final int? id;
final int shortId;
int? shortPlayId;
final String name;
final String description;
final String imageUrl;
final String horizontallyImg;
int collectTotal;
final int watchTotal;
final int episodeTotal;
final String? playSeconds;
bool? isCollect;
final String? videoUrl;
final Map<String, dynamic>? videoInfo;
final List<String>? category;
final List<NyCategoryModel>? categoryList;
final String tagType;
int? episode;
final int? process;
final int? buyType;
final int? searchClickTotal;
final int? shortPlayVideoId;
final int? currentEpisode;
int? historyTime;
NyDramaModel({
this.id,
required this.shortId,
this.shortPlayId,
required this.name,
required this.description,
required this.imageUrl,
required this.horizontallyImg,
required this.collectTotal,
required this.watchTotal,
required this.episodeTotal,
this.playSeconds,
this.isCollect,
this.videoUrl,
this.videoInfo,
this.category,
this.categoryList,
required this.tagType,
this.episode,
this.process,
this.buyType,
this.searchClickTotal,
this.shortPlayVideoId,
this.currentEpisode,
this.historyTime,
});
factory NyDramaModel.fromJson(Map<String, dynamic> json) {
return NyDramaModel(
id: json['id'] == null ? null : parseInt(json['id']),
shortId: parseInt(json['short_id']),
shortPlayId: json['short_play_id'] == null
? null
: parseInt(json['short_play_id']),
name: parseString(json['name']),
description: parseString(json['description']),
imageUrl: parseString(json['image_url']),
horizontallyImg: parseString(json['horizontally_img']),
collectTotal: parseInt(json['collect_total']),
watchTotal: parseInt(json['watch_total']),
episodeTotal: parseInt(json['episode_total']),
playSeconds: json['play_seconds'] as String?,
isCollect: json['is_collect'] == null
? null
: parseBool(json['is_collect']),
videoUrl: json['video_url'] as String?,
videoInfo: parseMap(json['video_info']),
category: parseStringList(json['category']),
categoryList: json['categoryList'] == null
? null
: parseModelList(json['categoryList'], NyCategoryModel.fromJson),
tagType: parseString(json['tag_type']),
episode: json['episode'] == null ? null : parseInt(json['episode']),
process: json['process'] == null ? null : parseInt(json['process']),
buyType: json['buy_type'] == null ? null : parseInt(json['buy_type']),
searchClickTotal: json['search_click_total'] == null
? null
: parseInt(json['search_click_total']),
shortPlayVideoId: json['short_play_video_id'] == null
? null
: parseInt(json['short_play_video_id']),
currentEpisode: json['current_episode'] == null
? null
: parseInt(json['current_episode']),
historyTime: json['history_time'] == null
? null
: parseInt(json['history_time']),
);
}
Map<String, dynamic> toJson() {
return {
'id': id,
'short_id': shortId,
'short_play_id': shortPlayId,
'name': name,
'description': description,
'image_url': imageUrl,
'horizontally_img': horizontallyImg,
'collect_total': collectTotal,
'watch_total': watchTotal,
'episode_total': episodeTotal,
'play_seconds': playSeconds,
'is_collect': isCollect,
'video_url': videoUrl,
'video_info': videoInfo,
'category': category,
'categoryList': categoryList?.map((item) => item.toJson()).toList(),
'tag_type': tagType,
'episode': episode,
'process': process,
'buy_type': buyType,
'search_click_total': searchClickTotal,
'short_play_video_id': shortPlayVideoId,
'current_episode': currentEpisode,
'history_time': historyTime,
};
}
NyDramaModel copyWith({
int? id,
int? shortId,
int? shortPlayId,
String? name,
String? description,
String? imageUrl,
String? horizontallyImg,
int? collectTotal,
int? watchTotal,
int? episodeTotal,
String? playSeconds,
bool? isCollect,
String? videoUrl,
Map<String, dynamic>? videoInfo,
List<String>? category,
List<NyCategoryModel>? categoryList,
String? tagType,
int? episode,
int? process,
int? buyType,
int? searchClickTotal,
int? shortPlayVideoId,
int? currentEpisode,
int? historyTime,
}) {
return NyDramaModel(
id: id ?? this.id,
shortId: shortId ?? this.shortId,
shortPlayId: shortPlayId ?? this.shortPlayId,
name: name ?? this.name,
description: description ?? this.description,
imageUrl: imageUrl ?? this.imageUrl,
horizontallyImg: horizontallyImg ?? this.horizontallyImg,
collectTotal: collectTotal ?? this.collectTotal,
watchTotal: watchTotal ?? this.watchTotal,
episodeTotal: episodeTotal ?? this.episodeTotal,
playSeconds: playSeconds ?? this.playSeconds,
isCollect: isCollect ?? this.isCollect,
videoUrl: videoUrl ?? this.videoUrl,
videoInfo: videoInfo ?? this.videoInfo,
category: category ?? this.category,
categoryList: categoryList ?? this.categoryList,
tagType: tagType ?? this.tagType,
episode: episode ?? this.episode,
process: process ?? this.process,
buyType: buyType ?? this.buyType,
searchClickTotal: searchClickTotal ?? this.searchClickTotal,
shortPlayVideoId: shortPlayVideoId ?? this.shortPlayVideoId,
currentEpisode: currentEpisode ?? this.currentEpisode,
historyTime: historyTime ?? this.historyTime,
);
}
}

View File

@ -0,0 +1,93 @@
import 'package:novyronst/common/model/parse_model.dart';
class NyEpisodeModel {
final int id;
final int shortId;
final int shortPlayId;
final int shortPlayVideoId;
final int episode;
final String videoUrl;
final int? promiseViewAd;
final int iaaPopUp;
bool isLock;
String playSeconds;
int? viewAdCount;
NyEpisodeModel({
required this.id,
required this.shortId,
required this.shortPlayId,
required this.shortPlayVideoId,
required this.episode,
required this.videoUrl,
required this.playSeconds,
required this.isLock,
this.promiseViewAd,
required this.iaaPopUp,
required this.viewAdCount,
});
factory NyEpisodeModel.fromJson(Map<String, dynamic> json) {
return NyEpisodeModel(
id: parseInt(json['id']),
shortId: parseInt(json['short_id']),
shortPlayId: parseInt(json['short_play_id']),
shortPlayVideoId: parseInt(json['short_play_video_id']),
episode: parseInt(json['episode']),
videoUrl: parseString(json['video_url']),
playSeconds: parseString(json['play_seconds']),
isLock: parseBool(json['is_lock']),
promiseViewAd: json['promise_view_ad'] == null
? null
: parseInt(json['promise_view_ad']),
iaaPopUp: parseInt(json['iaa_pop_up']),
viewAdCount: parseInt(json['view_ad_count']),
);
}
Map<String, dynamic> toJson() {
return {
'id': id,
'short_id': shortId,
'short_play_id': shortPlayId,
'short_play_video_id': shortPlayVideoId,
'episode': episode,
'video_url': videoUrl,
'promise_view_ad': promiseViewAd,
'iaa_pop_up': iaaPopUp,
'is_lock': isLock,
'play_seconds': playSeconds,
'view_ad_count': viewAdCount,
};
}
NyEpisodeModel copyWith({
int? id,
int? shortId,
int? shortPlayId,
int? shortPlayVideoId,
int? episode,
String? videoUrl,
bool? isLock,
String? playSeconds,
String? durationSeconds,
int? promiseViewAd,
int? viewAdCount,
int? iaaPopUp,
}) {
return NyEpisodeModel(
id: id ?? this.id,
shortId: shortId ?? this.shortId,
shortPlayId: shortPlayId ?? this.shortPlayId,
shortPlayVideoId: shortPlayVideoId ?? this.shortPlayVideoId,
episode: episode ?? this.episode,
videoUrl: videoUrl ?? this.videoUrl,
isLock: isLock ?? this.isLock,
playSeconds: playSeconds ?? this.playSeconds,
promiseViewAd: promiseViewAd ?? this.promiseViewAd,
viewAdCount: viewAdCount ?? this.viewAdCount,
iaaPopUp: iaaPopUp ?? this.iaaPopUp,
);
}
}

View File

@ -0,0 +1,39 @@
import 'ny_drama_model.dart';
class NyHomeModel {
final String? moduleKey;
final List<NyDramaModel> dataList;
const NyHomeModel({required this.moduleKey, required this.dataList});
factory NyHomeModel.fromJson(Map<String, dynamic> json) {
final data = json['data'];
List<NyDramaModel> videos = [];
if (data is Map<String, dynamic>) {
final list = data['list'];
if (list is List) {
videos = list.map((e) => NyDramaModel.fromJson(e)).toList();
}
} else if (data is List) {
videos = data.map((e) => NyDramaModel.fromJson(e)).toList();
}
return NyHomeModel(
moduleKey: json['module_key'] as String?,
dataList: videos,
);
}
Map<String, dynamic> toJson() {
return {'module_key': moduleKey, 'dataList': dataList};
}
NyHomeModel copyWith({String? moduleKey, dynamic data}) {
return NyHomeModel(
moduleKey: moduleKey ?? this.moduleKey,
dataList: data ?? dataList,
);
}
}

View File

@ -3,18 +3,26 @@ import 'package:flutter/services.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:flutter_smart_dialog/flutter_smart_dialog.dart';
import 'package:get/get.dart';
import 'package:novyronst/common/help/help_token.dart';
import 'package:novyronst/root/lib_export.dart';
import 'package:novyronst/root/root_page.dart';
import 'package:novyronst/tools/util/ny_device_info.dart';
void main() {
import 'common/help/help_pages.dart';
void main() async {
WidgetsFlutterBinding.ensureInitialized();
await initManage();
runApp(const RootApp());
}
Future<void> initManage() async {
await NyDeviceInfo.init();
await HelpToken().init();
}
class RootApp extends StatefulWidget {
@ -50,12 +58,11 @@ class _RootAppState extends State<RootApp> with WidgetsBindingObserver {
designSize: Size(375, 812),
child: GetMaterialApp(
debugShowCheckedModeBanner: false,
// translations: AppLanguage(),
locale: widget.locale ?? Get.deviceLocale,
fallbackLocale: const Locale('en'),
initialBinding: AppBindings(),
// initialRoute: SkyPages.initial,
// getPages: SkyPages.routes,
initialRoute: HelpRouters.launcher,
getPages: HelpPages.routes,
theme: ThemeData(
colorScheme: ColorScheme.fromSeed(
seedColor: ConstColor.themeColor,
@ -75,7 +82,6 @@ class _RootAppState extends State<RootApp> with WidgetsBindingObserver {
);
},
),
home: widget.home ?? RootPage(),
onInit: () {},
),
)

View File

@ -1,7 +1,13 @@
import 'package:easy_refresh/easy_refresh.dart';
import 'package:flutter/material.dart';
import 'package:novyronst/common/api/video_request.dart';
import 'package:novyronst/common/help/app_nav.dart';
import 'package:novyronst/common/model/ny_category_model.dart';
import 'package:novyronst/common/model/ny_drama_model.dart';
import 'package:novyronst/common/model/ny_home_model.dart';
import 'package:novyronst/pages/first/pages/search_page.dart';
import 'package:novyronst/pages/first/widgets/home_first_view.dart';
import 'package:novyronst/pages/first/widgets/home_rank_widget.dart';
import 'package:novyronst/pages/first/widgets/home_remaining_sections.dart';
import 'package:novyronst/pages/first/widgets/search_view.dart';
import 'package:novyronst/root/lib_export.dart';
@ -18,6 +24,41 @@ class FirstPage extends StatefulWidget {
}
class _RootPageState extends State<FirstPage> {
List<NyCategoryModel> _categories = [];
List<NyHomeModel> _homeDatas = [];
final EasyRefreshController _refreshController = EasyRefreshController(
controlFinishRefresh: true,
);
@override
void initState() {
super.initState();
_getCategoryData();
_getAllData();
}
void _getAllData() {
VideoRequest.getHomeData().then((value) {
setState(() {
_homeDatas = value;
});
for (NyHomeModel element in value) {
print('ele len===: ${element.moduleKey} : ${element.dataList.length}');
}
});
}
void _getCategoryData() {
VideoRequest.getCategoriesList().then((value) {
setState(() {
_categories = value;
});
});
}
@override
Widget build(BuildContext context) {
return AppBgPage(
@ -34,11 +75,17 @@ class _RootPageState extends State<FirstPage> {
slivers: [
SliverToBoxAdapter(child: HomeFirstView()),
SliverPadding(
padding: const EdgeInsets.only(left: 16, right: 10, top: 16),
padding: const EdgeInsets.only(left: 16, right: 10, top: 16, bottom: 8),
sliver: SliverToBoxAdapter(
child: HelpImage.asset(ConstImage.homeRank),
)
),
SliverPadding(
padding: const EdgeInsetsGeometry.symmetric(horizontal: 16),
sliver: SliverToBoxAdapter(
child: HomeRankWidget(),
),
),
const SliverToBoxAdapter(child: HomeRemainingSections()),
],
),

View File

@ -84,7 +84,7 @@ class _HomeFirstViewState extends State<HomeFirstView> {
);
}
_buildVideoItem() {
Widget _buildVideoItem() {
return Padding(
padding: const EdgeInsets.all(8),
child: Column(

View File

@ -0,0 +1,84 @@
import 'package:flutter/material.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:novyronst/common/const/const_string.dart';
import 'package:novyronst/tools/widgets/novy_com_widget.dart';
import '../../../tools/util/app_screen.dart';
import '../../../tools/widgets/novy_button_bg.dart';
import '../../widgets/cut_corner_clipper.dart';
import '../../widgets/ny_tag_widget.dart';
class HomeRankWidget extends StatelessWidget {
const HomeRankWidget({super.key});
@override
Widget build(BuildContext context) {
return CutCornerClipper(
width: AppScreen.screenWidth - 32,
cutCorner: CutCorner.bottomLeft,
cutSize: 40,
child: Padding(
padding: const EdgeInsets.all(8),
child: Column(
children: [
_buildRankList(),
const SizedBox(height: 5),
Row(
children: [
SizedBox(width: 20.w),
NovyButtonBg(text: 'Keep Watching', width: 308.w,)
],
)
],
),
),
);
}
Row _buildRankList() {
return Row(
children: [
_firstVideoView(),
const SizedBox(width: 8),
_otherVideoView(),
],
);
}
Widget _firstVideoView() {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Container(
width: 160.w, height: 240.w,
decoration: BoxDecoration(
color: Colors.red,
)
),
const SizedBox(height: 10),
NovyText('Star of the ocean', fontSize: 15,
color: Colors.black,
fontFamily: ConstFont.montMedium,
),
const SizedBox(height: 5),
NyTagWidget(text: 'Safiray'),
const SizedBox(height: 8),
],
);
}
Widget _otherVideoView() {
return Column(
children: List.generate(3, (index) {
return Container(
margin: const EdgeInsets.only(bottom: 8),
width: 160.w, height: 93.w,
decoration: BoxDecoration(
color: Colors.grey,
)
);
})
);
}
}

View File

@ -0,0 +1,52 @@
import 'package:flutter/material.dart';
import 'package:novyronst/common/api/user_request.dart';
import 'package:novyronst/common/help/app_nav.dart';
import 'package:novyronst/common/help/help_image.dart';
import 'package:novyronst/common/help/help_token.dart';
import 'package:novyronst/root/root_page.dart';
class LauncherPage extends StatefulWidget {
const LauncherPage({super.key});
@override
State<StatefulWidget> createState() {
return _LauncherPageState();
}
}
class _LauncherPageState extends State<LauncherPage> {
@override
void initState() {
super.initState();
_userRegister();
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: HelpImage.asset(ConstImage.launcher, fit: BoxFit.cover),
);
}
void _userRegister() async {
// token没有的话去注册
final tm = HelpToken();
String token = tm.get();
if (token.isNotEmpty) {
//
Future.delayed(const Duration(seconds: 1), () {
AppNav.off(RootPage());
});
return;
}
final res = await UserRequest.register();
if (res != null) {
tm.save(res.token);
AppNav.off(RootPage());
}
}
}

View File

@ -89,6 +89,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "3.0.7"
csslib:
dependency: transitive
description:
name: csslib
sha256: "09bad715f418841f976c77db72d5398dc1253c21fb9c0c7f0b0b985860b2d58e"
url: "https://pub.dev"
source: hosted
version: "1.0.2"
cupertino_icons:
dependency: "direct main"
description:
@ -129,6 +137,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "2.2.0"
easy_refresh:
dependency: "direct main"
description:
name: easy_refresh
sha256: "513a5dc82c044f8a9c9a3d600b3d5d3256070575bfd8761940533d8e209ba79b"
url: "https://pub.dev"
source: hosted
version: "3.5.1"
fake_async:
dependency: transitive
description:
@ -280,6 +296,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "2.0.2"
html:
dependency: transitive
description:
name: html
sha256: "6d1264f2dffa1b1101c25a91dff0dc2daee4c18e87cd8538729773c073dbf602"
url: "https://pub.dev"
source: hosted
version: "0.15.6"
http:
dependency: transitive
description:
@ -440,6 +464,22 @@ packages:
url: "https://pub.dev"
source: hosted
version: "1.9.1"
path_drawing:
dependency: transitive
description:
name: path_drawing
sha256: bbb1934c0cbb03091af082a6389ca2080345291ef07a5fa6d6e078ba8682f977
url: "https://pub.dev"
source: hosted
version: "1.0.1"
path_parsing:
dependency: transitive
description:
name: path_parsing
sha256: "883402936929eac138ee0a45da5b0f2c80f89913e6dc3bf77eb65b84b409c6ca"
url: "https://pub.dev"
source: hosted
version: "1.1.0"
path_provider:
dependency: transitive
description:
@ -725,6 +765,46 @@ packages:
url: "https://pub.dev"
source: hosted
version: "2.2.0"
video_player:
dependency: "direct main"
description:
name: video_player
sha256: "48a7bdaa38a3d50ec10c78627abdbfad863fdf6f0d6e08c7c3c040cfd80ae36f"
url: "https://pub.dev"
source: hosted
version: "2.11.1"
video_player_android:
dependency: transitive
description:
name: video_player_android
sha256: "877a6c7ba772456077d7bfd71314629b3fe2b73733ce503fc77c3314d43a0ca0"
url: "https://pub.dev"
source: hosted
version: "2.9.5"
video_player_avfoundation:
dependency: transitive
description:
name: video_player_avfoundation
sha256: "76097729ef0c976937945afa53f1ca3afa9b50c9a95909ba347bcf93270466fd"
url: "https://pub.dev"
source: hosted
version: "2.10.0"
video_player_platform_interface:
dependency: transitive
description:
name: video_player_platform_interface
sha256: e4ae5bc934b528e5b95c5e47be2812860186260cd3eed3ac62f5ed380fdd1613
url: "https://pub.dev"
source: hosted
version: "6.8.0"
video_player_web:
dependency: transitive
description:
name: video_player_web
sha256: "9f3c00be2ef9b76a95d94ac5119fb843dca6f2c69e6c9968f6f2b6c9e7afbdeb"
url: "https://pub.dev"
source: hosted
version: "2.4.0"
vm_service:
dependency: transitive
description:

View File

@ -31,6 +31,9 @@ dependencies:
android_id: ^0.5.1
logger: ^2.5.0
video_player: ^2.10.0
easy_refresh: ^3.4.0
dev_dependencies: