sqlite3_simple 2.3.0 copy "sqlite3_simple: ^2.3.0" to clipboard
sqlite3_simple: ^2.3.0 copied to clipboard

基于 Simple (支持中文和拼音的 SQLite fts5 全文搜索扩展) 和 sqlite3.dart 的 Flutter 库,用于 SQLite 中文和拼音全文搜索。

example/lib/main.dart

import 'dart:async';

import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter_localizations/flutter_localizations.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
import 'package:url_launcher/url_launcher.dart';

import 'data/db_manager_kind.dart';
import 'data/main_table_dao.dart';
import 'data/pinyin_dict_kind.dart';
import 'main_provider.dart';
import 'utils/font/font_loader.dart';
import 'utils/padding.dart';
import 'widget/dialog/usage_dialog.dart';
import 'widget/expand_collapse_strip.dart';
import 'widget/highlight_text.dart';
import 'widget/search_input.dart';
import 'widget/search_option_radio_row.dart';
import 'widget/dialog/search_result_dialog.dart';
import 'widget/search_result_list.dart';
import 'widget/expandable_table.dart';

void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  await AppFontLoader.instance.loadFirstScreen();
  runApp(
    ProviderScope(
      retry: (retryCount, error) =>
          ProviderContainer.defaultRetry(retryCount, error, maxRetries: 0),
      child: const MyApp(),
    ),
  );
  unawaited(AppFontLoader.instance.loadFull());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    /// 通过国际化设置中文环境以让 Flutter 使用正确的中文字体,主要是 Windows 平台
    const localizationsDelegates = [
      GlobalMaterialLocalizations.delegate,
      GlobalWidgetsLocalizations.delegate,
      GlobalCupertinoLocalizations.delegate,
    ];
    const supportedLocales = [Locale('zh', 'CN')];

    /// 自定义中文字体,避免 Flutter 默认加载字体的方式导致短时间的乱码
    final theme = ThemeData(fontFamily: HarmonyOsSansSC);
    final colorScheme = theme.colorScheme;
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      theme: theme,
      localizationsDelegates: localizationsDelegates,
      supportedLocales: supportedLocales,
      home: Scaffold(
        appBar: AppBar(
          centerTitle: MediaQuery.of(context).size.width > 420,
          title: const Text(
            'Simple 分词器 示例',
            style: TextStyle(fontWeight: FontWeight.bold, fontSize: 18),
          ),
          backgroundColor: colorScheme.primary,
          foregroundColor: colorScheme.onPrimary,
          actionsPadding: const EdgeInsetsDirectional.only(end: P.small),
          actions: buildActions(),
        ),
        body: SafeArea(
          child: Column(
            mainAxisSize: MainAxisSize.max,
            children: [
              buildSearchBar(),
              buildSearchOptions(context),
              Expanded(child: buildSearchResult()),
            ],
          ),
        ),
      ),
    );
  }

  /// 右上角功能按钮
  List<Widget> buildActions() {
    return [
      Consumer(
        builder: (context, ref, _) => IconButton(
          tooltip: '刷新数据',
          onPressed: () => refreshDbData(ref),
          icon: const Icon(Icons.refresh),
        ),
      ),
      Builder(
        builder: (context) => IconButton(
          tooltip: '使用说明',
          onPressed: () => showDialog(
            context: context,
            builder: (context) => const UsageDialog(),
          ),
          icon: const Icon(Icons.info_outline_rounded),
        ),
      ),
      IconButton(
        tooltip: 'Github 仓库',
        onPressed: () => launchUrl(
          Uri.parse('https://github.com/SageMik/sqlite3_simple'),
          webOnlyWindowName: '_blank',
        ),
        icon: const FaIcon(FontAwesomeIcons.github, size: 20),
      ),
    ];
  }

  /// 搜索栏
  Widget buildSearchBar() {
    return Container(
      width: double.infinity,
      padding: const EdgeInsets.only(
        left: P.middle,
        right: P.middle,
        top: P.middle,
      ),
      child: Consumer(
        builder: (context, ref, _) {
          return SearchInput(
            onChanged: ref.read(searchQueryProvider.notifier).update,
          );
        },
      ),
    );
  }

  /// 搜索栏下方选项
  Widget buildSearchOptions(BuildContext context) {
    return Container(
      width: double.infinity,
      padding: const EdgeInsets.fromLTRB(P.middle, P.middle, P.middle, 0),
      child: Consumer(
        builder: (context, ref, _) {
          final moreOpen = ref.watch(searchOptionsMoreOpenProvider);
          return ExpandableTable(
            expanded: moreOpen,
            pinnedRowCount: 1,
            trailing: ExpandCollapseStrip(
              expanded: moreOpen,
              onTap: () => ref
                  .read(searchOptionsMoreOpenProvider.notifier)
                  .update(!ref.read(searchOptionsMoreOpenProvider)),
            ),
            child: Table(
              columnWidths: searchOptionTableColumnWidths,
              defaultVerticalAlignment: TableCellVerticalAlignment.middle,
              children: [
                SearchOptionRadioRow<DbManagerKind>(
                  label: "数据库实现:",
                  value: ref.watch(dbManagerKindProvider),
                  options: dbManagerKind2uiString,
                  onChanged: (v) async {
                    if (ref.read(dbManagerKindProvider) == v) {
                      // 重复点击刷新为新的随机数据
                      await refreshDbData(ref);
                    } else {
                      if (kDebugMode) {
                        print("切换数据库至:${dbManagerKind2uiString[v]}");
                      }
                      ref.read(dbManagerKindProvider.notifier).update(v);
                    }
                  },
                ),
                SearchOptionRadioRow<Tokenizer>(
                  label: "分词器:",
                  value: ref.watch(tokenizerProvider),
                  options: tokenizer2uiString,
                  onChanged: (v) =>
                      ref.read(tokenizerProvider.notifier).update(v),
                ),
                SearchOptionRadioRow<PinyinDictKind>(
                  label: "拼音文件:",
                  value: ref.watch(pinyinDictKindProvider),
                  options: pinyinDictKind2uiString,
                  isLast: true,
                  onChanged: (v) =>
                      ref.read(pinyinDictKindProvider.notifier).update(v),
                ),
              ],
            ),
          );
        },
      ),
    );
  }

  /// 高亮文本构建器
  static final highlightTextBuilder = HighlightTextSpanBuilder(
    (src) => src.copyWith(color: Colors.red),
  );

  static const searchOptionTableColumnWidths = <int, TableColumnWidth>{
    0: IntrinsicColumnWidth(),
    1: FlexColumnWidth(),
  };

  /// 搜索结果
  Widget buildSearchResult() {
    return Consumer(
      builder: (context, ref, _) {
        final result = ref.watch(searchResultProvider);
        return result.when(
          skipLoadingOnRefresh: true,
          skipLoadingOnReload: true,
          data: (results) => AnimatedSwitcher(
            duration: kThemeAnimationDuration,
            child: results == null
                ? const Center(child: CircularProgressIndicator())
                : SearchResultList(
                    results: results,
                    highlightTextBuilder: highlightTextBuilder,
                    onItemTap: (context, row) {
                      showDialog(
                        context: context,
                        builder: (context) =>
                            SearchResultDialog(row, highlightTextBuilder),
                      );
                    },
                  ),
          ),
          loading: () => const SizedBox.shrink(),
          error: (error, stack) => Container(
            height: double.infinity,
            padding: const EdgeInsets.symmetric(horizontal: P.middle),
            width: double.infinity,
            child: SingleChildScrollView(
              child: SelectionArea(child: Text('错误: $error\n\n堆栈:$stack')),
            ),
          ),
        );
      },
    );
  }

  /// 刷新数据库数据
  Future<void> refreshDbData(WidgetRef ref) async {
    final dbManager = await ref.read(dbManagerProvider.future);
    await dbManager.dao.updateAll();
    ref.invalidate(searchResultProvider);
    await ref.read(searchResultProvider.future);
  }
}
2
likes
125
points
167
downloads

Documentation

API reference

Publisher

unverified uploader

Weekly Downloads

基于 Simple (支持中文和拼音的 SQLite fts5 全文搜索扩展) 和 sqlite3.dart 的 Flutter 库,用于 SQLite 中文和拼音全文搜索。

Homepage
Repository (GitHub)
View/report issues

License

MIT (license)

Dependencies

flutter, flutter_web_plugins, path, plugin_platform_interface, sqlite3, wasd, web

More

Packages that depend on sqlite3_simple

Packages that implement sqlite3_simple