Blame view

lib/pages/video/zone/video_zone_page.dart 5.88 KB
383462ef   吴启风   feat: 新增视频专区列表与播放功能
1
2
  import 'package:cached_network_image/cached_network_image.dart';
  import 'package:flutter/material.dart';
383462ef   吴启风   feat: 新增视频专区列表与播放功能
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
  import 'package:flutter_screenutil/flutter_screenutil.dart';
  import 'package:wow_english/common/dialogs/show_dialog.dart';
  import 'package:wow_english/common/request/dao/video_dao.dart';
  import 'package:wow_english/common/widgets/we_app_bar.dart';
  import 'package:wow_english/route/route.dart';
  
  import 'video_zone_item.dart';
  
  class VideoZonePage extends StatefulWidget {
    const VideoZonePage({super.key});
  
    @override
    State<VideoZonePage> createState() => _VideoZonePageState();
  }
  
  class _VideoZonePageState extends State<VideoZonePage> {
    late Future<List<VideoZoneItem>> _itemsFuture;
  
    @override
    void initState() {
      super.initState();
383462ef   吴启风   feat: 新增视频专区列表与播放功能
24
25
26
      _itemsFuture = VideoDao.list();
    }
  
383462ef   吴启风   feat: 新增视频专区列表与播放功能
27
    void _reload() {
9475aa49   吴启风   feat: 优化视频专区列表布局与...
28
29
30
      setState(() {
        _itemsFuture = VideoDao.list();
      });
383462ef   吴启风   feat: 新增视频专区列表与播放功能
31
32
33
34
    }
  
    @override
    Widget build(BuildContext context) {
5bc84eff   吴启风   Revert "feat: 优化视...
35
      return Scaffold(
9475aa49   吴启风   feat: 优化视频专区列表布局与...
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
          backgroundColor: Colors.white,
          appBar: const WEAppBar(
            titleText: '视频专区',
            centerTitle: false,
          ),
          body: FutureBuilder<List<VideoZoneItem>>(
            future: _itemsFuture,
            builder: (context, snapshot) {
              if (snapshot.connectionState == ConnectionState.waiting) {
                return const Center(child: CircularProgressIndicator());
              }
              if (snapshot.hasError) {
                return _VideoLoadError(onRetry: _reload);
              }
              final items = snapshot.data ?? const <VideoZoneItem>[];
              if (items.isEmpty) {
                return const Center(
                  child: Text(
                    '暂无视频',
                    style: TextStyle(color: Color(0xFF999999), fontSize: 18),
                  ),
                );
              }
              return RefreshIndicator(
                onRefresh: () async {
                  final future = VideoDao.list();
                  setState(() => _itemsFuture = future);
                  await future;
                },
                child: LayoutBuilder(
                  builder: (context, constraints) {
54f62f82   吴启风   fix: 自适应视频标题高度避免文字裁切
67
                    final titleStyle = _VideoCard.createTitleStyle(context);
9475aa49   吴启风   feat: 优化视频专区列表布局与...
68
69
70
                    return GridView.builder(
                      physics: const AlwaysScrollableScrollPhysics(),
                      padding: EdgeInsets.fromLTRB(
5bc84eff   吴启风   Revert "feat: 优化视...
71
                        14.w,
9475aa49   吴启风   feat: 优化视频专区列表布局与...
72
                        10.h,
5bc84eff   吴启风   Revert "feat: 优化视...
73
                        14.w,
9475aa49   吴启风   feat: 优化视频专区列表布局与...
74
75
76
                        16.h,
                      ),
                      gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
5bc84eff   吴启风   Revert "feat: 优化视...
77
                        crossAxisCount: 4,
9475aa49   吴启风   feat: 优化视频专区列表布局与...
78
                        mainAxisSpacing: 14.h,
5bc84eff   吴启风   Revert "feat: 优化视...
79
80
                        crossAxisSpacing: 12.w,
                        childAspectRatio: 1.55,
9475aa49   吴启风   feat: 优化视频专区列表布局与...
81
82
83
84
85
                      ),
                      itemCount: items.length,
                      itemBuilder: (context, index) => _VideoCard(
                        item: items[index],
                        onTap: () => _openVideo(items, index),
54f62f82   吴启风   fix: 自适应视频标题高度避免文字裁切
86
                        titleStyle: titleStyle,
9475aa49   吴启风   feat: 优化视频专区列表布局与...
87
88
89
                      ),
                    );
                  },
383462ef   吴启风   feat: 新增视频专区列表与播放功能
90
91
                ),
              );
9475aa49   吴启风   feat: 优化视频专区列表布局与...
92
93
            },
          ),
5bc84eff   吴启风   Revert "feat: 优化视...
94
        );
383462ef   吴启风   feat: 新增视频专区列表与播放功能
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
    }
  
    void _openVideo(List<VideoZoneItem> items, int index) {
      final item = items[index];
      if (!item.accessible || item.videoUrl.isEmpty) {
        showTwoActionDialog('提示', '取消', '去购买', '购买课程后即可观看视频。', leftTap: popPage,
            rightTap: () {
          popPage();
          pushNamed(AppRouteName.shop);
        });
        return;
      }
      Navigator.of(context).pushNamed(
        AppRouteName.videoZonePlayer,
        arguments: {
          'items': items
              .where((video) => video.accessible && video.videoUrl.isNotEmpty)
              .toList(),
          'initialVideoId': item.id,
        },
5bc84eff   吴启风   Revert "feat: 优化视...
115
      ).then((_) => _reload());
383462ef   吴启风   feat: 新增视频专区列表与播放功能
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
    }
  }
  
  class _VideoLoadError extends StatelessWidget {
    const _VideoLoadError({required this.onRetry});
  
    final VoidCallback onRetry;
  
    @override
    Widget build(BuildContext context) {
      return Center(
        child: Column(
          mainAxisSize: MainAxisSize.min,
          children: [
            const Text(
              '视频加载失败,请稍后重试',
              style: TextStyle(color: Color(0xFF999999), fontSize: 18),
            ),
            const SizedBox(height: 12),
            FilledButton(onPressed: onRetry, child: const Text('重新加载')),
          ],
        ),
      );
    }
  }
  
  class _VideoCard extends StatelessWidget {
54f62f82   吴启风   fix: 自适应视频标题高度避免文字裁切
143
144
145
146
147
    const _VideoCard({
      required this.item,
      required this.onTap,
      required this.titleStyle,
    });
383462ef   吴启风   feat: 新增视频专区列表与播放功能
148
149
150
  
    final VideoZoneItem item;
    final VoidCallback onTap;
54f62f82   吴启风   fix: 自适应视频标题高度避免文字裁切
151
152
153
154
155
156
157
158
    final TextStyle titleStyle;
  
    static TextStyle createTitleStyle(BuildContext context) => TextStyle(
          color: const Color(0xFF222222),
          fontFamily: null,
          fontSize: 17.sp,
          fontWeight: FontWeight.w500,
        );
383462ef   吴启风   feat: 新增视频专区列表与播放功能
159
160
161
162
  
    @override
    Widget build(BuildContext context) {
      return InkWell(
c67962ab   吴启风   feat: 视频卡片点击区域和封面...
163
        borderRadius: BorderRadius.circular(12.r),
383462ef   吴启风   feat: 新增视频专区列表与播放功能
164
165
166
167
        onTap: onTap,
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
5bc84eff   吴启风   Revert "feat: 优化视...
168
            Expanded(
383462ef   吴启风   feat: 新增视频专区列表与播放功能
169
              child: ClipRRect(
c67962ab   吴启风   feat: 视频卡片点击区域和封面...
170
                borderRadius: BorderRadius.circular(12.r),
9475aa49   吴启风   feat: 优化视频专区列表布局与...
171
172
173
174
175
176
177
178
179
180
181
182
                child: CachedNetworkImage(
                  imageUrl: item.coverUrl,
                  fit: BoxFit.cover,
                  placeholder: (_, __) => const ColoredBox(
                    color: Color(0xFFF2F2F2),
                    child: Center(child: CircularProgressIndicator()),
                  ),
                  errorWidget: (_, __, ___) => const ColoredBox(
                    color: Color(0xFFF2F2F2),
                    child: Icon(Icons.broken_image_outlined,
                        color: Color(0xFFAAAAAA)),
                  ),
383462ef   吴启风   feat: 新增视频专区列表与播放功能
183
184
185
186
                ),
              ),
            ),
            SizedBox(height: 5.h),
54f62f82   吴启风   fix: 自适应视频标题高度避免文字裁切
187
188
189
190
191
            Text(
              item.title,
              maxLines: 1,
              overflow: TextOverflow.ellipsis,
              style: titleStyle,
383462ef   吴启风   feat: 新增视频专区列表与播放功能
192
193
194
195
196
197
            ),
          ],
        ),
      );
    }
  }