This commit is contained in:
2026-02-13 15:53:22 +01:00
commit 25271189b5
639 changed files with 49083 additions and 0 deletions

View File

@@ -0,0 +1,50 @@
import 'dart:convert';
import 'package:flutter/cupertino.dart';
import 'package:hiddingsel_app/services/environment.dart';
import 'package:webview_flutter/webview_flutter.dart';
class HtmlView extends StatefulWidget {
final String _html;
final String html;
HtmlView(this.html)
: _html = Uri.dataFromString(html, mimeType: 'text/html', encoding: utf8)
.toString();
@override
State<StatefulWidget> createState() => _HtmlViewState();
}
class _HtmlViewState extends State<HtmlView> {
double? _height;
@override
Widget build(BuildContext context) {
WebViewController wbController = WebViewController()
..enableZoom(true)
..setJavaScriptMode(JavaScriptMode.unrestricted);
wbController.setNavigationDelegate(
NavigationDelegate(
onPageFinished: (String) async {
if (_height == null) {
var heightString = (await wbController
.runJavaScriptReturningResult(
'document.documentElement.scrollHeight;'));
setState(() {
_height = double.parse(heightString.toString());
});
}
}
),
);
wbController.loadHtmlString(widget.html);
return SizedBox(
height: _height ?? 1,
child: WebViewWidget(
controller: wbController,
),
);
}
}

View File

@@ -0,0 +1,60 @@
import 'package:flutter/material.dart';
import 'package:hiddingsel_app/constants/constant.dart';
/**
* Inspiration: ToggleButtons https://www.youtube.com/watch?v=kVEguaQWGAY
*
*/
class IconSwitch extends StatelessWidget {
final Future<bool> _initFavorite;
final Function(bool favorite) _onFavorite;
final Gradient _gradientColor;
final Color _defaultColor;
final IconData _iconFavorite;
final IconData _iconDefavorite;
IconSwitch(this._onFavorite, {initFavorite, gradientColor, defaultColor = UIColors.grey5, iconFavorite = Icons.star, iconDefavorite = Icons.star_border_outlined})
: _initFavorite = initFavorite ?? Future.value(false),
_gradientColor = gradientColor ??
LinearGradient(colors: [
UIColors.white,
UIColors.white,
]),
_defaultColor = defaultColor,
_iconFavorite = iconFavorite,
_iconDefavorite = iconDefavorite;
@override
Widget build(BuildContext context) => FutureBuilder(
future: _initFavorite,
builder: (context, AsyncSnapshot snapshot) {
bool _favorite = snapshot.data ?? false;
return StatefulBuilder(
builder: (context, setState) => IconButton(
icon: _favorite
? ShaderMask(
shaderCallback: (Rect bounds) {
return _gradientColor.createShader(bounds);
},
child: Icon(
_iconFavorite,
color: Colors.white,
),
)
: Icon(
_iconDefavorite,
color: _defaultColor,
),
tooltip: 'Favorite',
onPressed: () {
_onFavorite(!_favorite);
setState(() {
_favorite = !_favorite;
});
},
),
);
},
);
}

View File

@@ -0,0 +1,109 @@
import 'package:flutter/material.dart';
class ZoomableImage extends StatelessWidget {
final ImageProvider _image;
final UniqueKey _key = UniqueKey();
final ImageFrameBuilder? frameBuilder;
final ImageLoadingBuilder? loadingBuilder;
final ImageErrorWidgetBuilder? errorBuilder;
final double? width;
final double? height;
final Color? color;
final Animation<double>? opacity;
final FilterQuality filterQuality;
final BlendMode? colorBlendMode;
final BoxFit? fit;
final AlignmentGeometry alignment;
final ImageRepeat repeat;
final Rect? centerSlice;
final bool matchTextDirection;
final bool gaplessPlayback;
final String? semanticLabel;
final bool excludeFromSemantics;
final bool isAntiAlias;
ZoomableImage(this._image, {
Key? key,
this.frameBuilder,
this.loadingBuilder,
this.errorBuilder,
this.semanticLabel,
this.excludeFromSemantics = false,
this.width,
this.height,
this.color,
this.opacity,
this.colorBlendMode,
this.fit,
this.alignment = Alignment.center,
this.repeat = ImageRepeat.noRepeat,
this.centerSlice,
this.matchTextDirection = false,
this.gaplessPlayback = false,
this.isAntiAlias = false,
this.filterQuality = FilterQuality.low,}) : super(key: key);
@override
Widget build(BuildContext context) => GestureDetector(
child: Hero(
tag: 'zoomImageHero${_key.hashCode}',
child: Image(
image: _image,
key: _key,
frameBuilder: frameBuilder,
loadingBuilder: loadingBuilder,
errorBuilder: errorBuilder,
semanticLabel: semanticLabel,
excludeFromSemantics: excludeFromSemantics,
width: width,
height: height,
color: color,
opacity: opacity,
colorBlendMode: colorBlendMode,
fit: fit,
alignment: alignment,
repeat: repeat,
centerSlice: centerSlice,
matchTextDirection: matchTextDirection,
gaplessPlayback: gaplessPlayback,
filterQuality: filterQuality,
isAntiAlias: isAntiAlias,
),
),
onTap: () {
Navigator.push(context, MaterialPageRoute(builder: (_) {
return _ImageDetail(_image, _key);
}));
},
);
}
class _ImageDetail extends StatelessWidget {
final ImageProvider _image;
const _ImageDetail(this._image, Key key) : super(key: key);
@override
Widget build(BuildContext context) {
return InteractiveViewer(
panEnabled: true,
minScale: 1,
maxScale: 3,
child: Scaffold(
body: GestureDetector(
child: Center(
child: Hero(
tag: 'zoomImageHero${super.key.hashCode}',
child: Image(image: _image),
)
),
onTap: () {
Navigator.pop(context);
},
),
),
);
}
}

View File

@@ -0,0 +1,31 @@
import 'package:flutter/material.dart';
import 'dart:math';
import 'helper.dart';
class ColumnExtension extends StatelessWidget {
final Function(BuildContext, int) _itemBuilder;
final int _itemCount;
final MainAxisAlignment _mainAxisAlignment;
ColumnExtension.builder(
{required itemBuilder, required itemCount, mainAxisAlignment})
: _itemBuilder = itemBuilder,
_itemCount = itemCount,
_mainAxisAlignment = mainAxisAlignment ?? MainAxisAlignment.start;
ColumnExtension.separated(
{required itemBuilder,
required separatorBuilder,
required int itemCount,
mainAxisAlignment})
: _itemBuilder = getSeparatedItemBuilder(itemBuilder, separatorBuilder),
_itemCount = max(0, itemCount * 2 - 1),
_mainAxisAlignment = mainAxisAlignment;
@override
Widget build(BuildContext context) => Column(
mainAxisAlignment: _mainAxisAlignment,
children:
List<Widget>.generate(_itemCount, (i) => _itemBuilder(context, i)),
);
}

View File

@@ -0,0 +1,12 @@
import 'package:flutter/cupertino.dart';
IndexedWidgetBuilder getSeparatedItemBuilder(IndexedWidgetBuilder itemBuilder,
IndexedWidgetBuilder separatorBuilder) {
return (context, index) {
if (index.isEven) {
return itemBuilder(context, index ~/ 2);
} else {
return separatorBuilder(context, index ~/ 2);
}
};
}

View File

@@ -0,0 +1,31 @@
import 'package:flutter/material.dart';
import 'dart:math';
import 'helper.dart';
class RowExtension extends StatelessWidget {
final Function(BuildContext, int) _itemBuilder;
final int _itemCount;
final MainAxisAlignment _mainAxisAlignment;
RowExtension.builder(
{required itemBuilder, required itemCount, mainAxisAlignment})
: _itemBuilder = itemBuilder,
_itemCount = itemCount,
_mainAxisAlignment = mainAxisAlignment ?? MainAxisAlignment.start;
RowExtension.separated(
{required itemBuilder,
required separatorBuilder,
required int itemCount,
mainAxisAlignment})
: _itemBuilder = getSeparatedItemBuilder(itemBuilder, separatorBuilder),
_itemCount = max(0, itemCount * 2 - 1),
_mainAxisAlignment = mainAxisAlignment;
@override
Widget build(BuildContext context) => Row(
mainAxisAlignment: _mainAxisAlignment,
children:
List<Widget>.generate(_itemCount, (i) => _itemBuilder(context, i)),
);
}