Skip to content

Commit

Permalink
🔖 v1.1.0
Browse files Browse the repository at this point in the history
  • Loading branch information
yaoxieyoulei committed Apr 1, 2024
1 parent 6d3d309 commit 2c5eeaa
Show file tree
Hide file tree
Showing 47 changed files with 1,993 additions and 869 deletions.
12 changes: 9 additions & 3 deletions .github/workflows/release_ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -41,11 +41,17 @@ jobs:
- name: 下载项目依赖
run: flutter pub get

- name: flutter build apk
run: flutter build apk --release --split-per-abi
- name: 解码生成 jks
run: echo $KEYSTORE_BASE64 | base64 -di > android/app/keystore.jks
env:
KEYSTORE_BASE64: ${{ secrets.KEYSTORE_BASE64 }}

- name: flutter build apk
run: flutter build apk --release
run: flutter build apk --release --target-platform android-arm64,android-arm
env:
KEYSTORE_PASSWORD: ${{ secrets.KEYSTORE_PASSWORD }}
KEY_ALIAS: ${{ secrets.KEY_ALIAS }}
KEY_PASSWORD: ${{ secrets.KEY_PASSWORD}}

- name: 获取版本号
id: version
Expand Down
25 changes: 25 additions & 0 deletions .vscode/launch.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
{
// 使用 IntelliSense 了解相关属性。
// 悬停以查看现有属性的描述。
// 欲了解更多信息,请访问: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"name": "my_tv",
"request": "launch",
"type": "dart"
},
{
"name": "my_tv (profile mode)",
"request": "launch",
"type": "dart",
"flutterMode": "profile"
},
{
"name": "my_tv (release mode)",
"request": "launch",
"type": "dart",
"flutterMode": "release"
}
]
}
12 changes: 3 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,3 @@
<div align="center">
<img width="200" height="200" src="./screenshots/logo.webp">
</div>



<div align="center">
<h1>我的电视</h1>
<div align="center">
Expand Down Expand Up @@ -32,12 +26,12 @@

## 功能

目前着重移动端(Android),暂时没有适配桌面端、Pad端等
目前着重移动端(Android)、电视端(Android),暂时没有适配桌面端、Pad端等

- [ ] 选台反转
- [x] 选台反转
- [x] 数字选台
- [ ] 开机自启
- [ ] 应用内更新
- [ ] 应用更新

## 开发环境

Expand Down
28 changes: 25 additions & 3 deletions android/app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,17 @@ if (flutterVersionName == null) {
flutterVersionName = '1.0'
}

def keystorePropertiesFile = rootProject.file('key.properties')
def keystoreProperties = new Properties()
if (keystorePropertiesFile.exists()) {
keystoreProperties.load(new FileInputStream(keystorePropertiesFile))
}

def _storeFile = file(System.getenv("KEYSTORE") ?: keystoreProperties["storeFile"] ?: "keystore.jks")
def _storePassword = System.getenv("KEYSTORE_PASSWORD") ?: keystoreProperties["storePassword"]
def _keyAlias = System.getenv("KEY_ALIAS") ?: keystoreProperties["keyAlias"]
def _keyPassword = System.getenv("KEY_PASSWORD") ?: keystoreProperties["keyPassword"]

android {
namespace "com.example.my_tv"
compileSdk flutter.compileSdkVersion
Expand All @@ -45,11 +56,23 @@ android {
applicationId "top.yogiczy.my_tv"
// You can update the following values to match your application needs.
// For more information, see: https://docs.flutter.dev/deployment/android#reviewing-the-gradle-build-configuration.
minSdkVersion 21
minSdkVersion flutter.minSdkVersion
targetSdkVersion flutter.targetSdkVersion
versionCode flutterVersionCode.toInteger()
versionName flutterVersionName
multiDexEnabled true
}

signingConfigs {
// 添加签名配置
release {
// 配置密钥库文件的位置、别名、密码等信息
storeFile _storeFile
storePassword _storePassword
keyAlias _keyAlias
keyPassword _keyPassword
v1SigningEnabled true
v2SigningEnabled true
}
}

buildTypes {
Expand All @@ -66,5 +89,4 @@ flutter {
}

dependencies {
implementation 'com.android.support:multidex:1.0.3'
}
3 changes: 2 additions & 1 deletion android/gradle/wrapper/gradle-wrapper.properties
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#Sun Mar 31 18:39:28 CST 2024
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.7-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-7.6.3-all.zip
3 changes: 3 additions & 0 deletions lib/common/enums/index.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
library enums;

export 'iptv_settings.dart';
52 changes: 52 additions & 0 deletions lib/common/enums/iptv_settings.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import 'package:my_tv/common/index.dart';

/// 直播设置
enum IPTVSetting {
/// 初始直播源序号
initialIPTVIdx,

/// 换台反转
channelChangeFlip,

/// 直播源类型
iptvType,

/// 直播源缓存时间
iptvCacheTime,
}

/// 直播源类型
enum IPTVSettingIPTVType {
/// 完整
full,

/// 精简
simple,
}

extension IPTVSettingIPTVTypeExtension on IPTVSettingIPTVType {
String get name {
switch (this) {
case IPTVSettingIPTVType.full:
return '完整';
case IPTVSettingIPTVType.simple:
return '精简';
}
}
}

/// 直播设置
class IPTVSettings {
static int get initialIPTVIdx => Global.prefs.getInt(IPTVSetting.initialIPTVIdx.toString()) ?? 0;
static set initialIPTVIdx(int value) => Global.prefs.setInt(IPTVSetting.initialIPTVIdx.toString(), value);

static bool get channelChangeFlip => Global.prefs.getBool(IPTVSetting.channelChangeFlip.toString()) ?? false;
static set channelChangeFlip(bool value) => Global.prefs.setBool(IPTVSetting.channelChangeFlip.toString(), value);

static IPTVSettingIPTVType get iptvType =>
IPTVSettingIPTVType.values[Global.prefs.getInt(IPTVSetting.iptvType.toString()) ?? 0];
static set iptvType(IPTVSettingIPTVType value) => Global.prefs.setInt(IPTVSetting.iptvType.toString(), value.index);

static int get iptvCacheTime => Global.prefs.getInt(IPTVSetting.iptvCacheTime.toString()) ?? 0;
static set iptvCacheTime(int value) => Global.prefs.setInt(IPTVSetting.iptvCacheTime.toString(), value);
}
2 changes: 2 additions & 0 deletions lib/common/index.dart
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,5 @@ export 'style/index.dart';
export 'utils/index.dart';
export 'values/index.dart';
export 'widgets/index.dart';
export 'enums/index.dart';
export 'stores/index.dart';
6 changes: 3 additions & 3 deletions lib/common/models/iptv.dart
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ class IPTV {
late int channel;

/// 所属分组
late IPTVGroup group;
late int groupIdx;

/// 名称
late String name;
Expand All @@ -21,15 +21,15 @@ class IPTV {
IPTV({
required this.idx,
required this.channel,
required this.group,
required this.groupIdx,
required this.name,
required this.url,
this.logo,
});

@override
String toString() {
return 'IPTV{idx: $idx, channel: $channel, group: $group, name: $name, url: $url, logo: $logo}';
return 'IPTV{idx: $idx, channel: $channel, groupIdx: $groupIdx, name: $name, url: $url, logo: $logo}';
}
}

Expand Down
4 changes: 4 additions & 0 deletions lib/common/stores/index.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
library stores;

export './iptv.dart';
export './player.dart';
78 changes: 78 additions & 0 deletions lib/common/stores/iptv.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
import 'dart:async';

import 'package:mobx/mobx.dart';
import 'package:my_tv/common/index.dart';

part 'iptv.g.dart';

class IPTVStore = IPTVStoreBase with _$IPTVStore;

abstract class IPTVStoreBase with Store {
/// 直播源分组列表
@observable
List<IPTVGroup> iptvGroupList = [];

/// 直播源列表
@observable
List<IPTV> iptvList = [];

/// 当前直播源
@observable
IPTV currentIPTV = IPTV(idx: 0, channel: 0, groupIdx: 0, name: '', url: '');

/// 显示iptv信息
@observable
bool iptvInfoVisible = false;

/// 选台频道号
@observable
String channelNo = '';

/// 确认选台定时器
Timer? confirmChannelTimer;

/// 获取上一个直播源
IPTV getPrevIPTV({IPTV? iptv}) {
final prevIdx = iptvList.indexOf(iptv ?? currentIPTV) - 1;
return prevIdx < 0 ? iptvList.last : iptvList.elementAt(prevIdx);
}

/// 获取下一个直播源
IPTV getNextIPTV({IPTV? iptv}) {
final nextIdx = iptvList.indexOf(iptv ?? currentIPTV) + 1;
return nextIdx >= iptvList.length ? iptvList.first : iptvList.elementAt(nextIdx);
}

/// 获取上一个分组直播源
IPTV getPrevGroupIPTV({IPTV? iptv}) {
final prevIdx = (iptv?.groupIdx ?? currentIPTV.groupIdx) - 1;
return prevIdx < 0 ? iptvGroupList.last.list.first : iptvGroupList.elementAt(prevIdx).list.first;
}

/// 获取下一个分组直播源
IPTV getNextGroupIPTV({IPTV? iptv}) {
final nextIdx = (iptv?.groupIdx ?? currentIPTV.groupIdx) + 1;
return nextIdx >= iptvGroupList.length
? iptvGroupList.first.list.first
: iptvGroupList.elementAt(nextIdx).list.first;
}

/// 刷新直播源列表
@action
Future<void> refreshIPTVList() async {
iptvGroupList = IPTVUtil.parseFromM3u(await IPTVUtil.fetchM3u());
iptvList = iptvGroupList.expand((e) => e.list).toList();
}

void inputChannelNo(String no) {
confirmChannelTimer?.cancel();

channelNo += no;
confirmChannelTimer = Timer(Duration(seconds: 4 - channelNo.length), () {
final channel = int.tryParse(channelNo) ?? 0;
final iptv = iptvList.firstWhere((e) => e.channel == channel, orElse: () => currentIPTV);
currentIPTV = iptv;
channelNo = '';
});
}
}
Loading

0 comments on commit 2c5eeaa

Please sign in to comment.