Compare commits

...

5 Commits

Author SHA1 Message Date
fe7c5b65e8 new itemview
All checks were successful
continuous-integration/drone/push Build is passing
2022-05-30 07:34:46 +02:00
40afd685dd refresh 2022-05-30 07:34:42 +02:00
dd9a61bcca draft! 2022-05-30 07:34:35 +02:00
ca98d86e26 Itempage
All checks were successful
continuous-integration/drone/push Build is passing
continuous-integration/drone/tag Build is passing
2022-05-30 02:29:52 +02:00
89658791bb test :D
All checks were successful
continuous-integration/drone/push Build is passing
2022-05-29 20:19:48 +02:00
7 changed files with 168 additions and 29 deletions

View File

@ -5,7 +5,6 @@ steps:
- name: build
image: cirrusci/flutter:latest
commands:
- flutter doctor
- flutter build apk --release
- name: gitea_release
image: plugins/gitea-release
@ -13,7 +12,8 @@ steps:
api_key:
from_secret: gitea_api_key
base_url: https://git.lat
draft: true
files: build/app/outputs/apk/release/app-release.apk
trigger:
event:
- tag
when:
event:
- tag

25
.vscode/launch.json vendored Normal file
View File

@ -0,0 +1,25 @@
{
// Verwendet IntelliSense zum Ermitteln möglicher Attribute.
// Zeigen Sie auf vorhandene Attribute, um die zugehörigen Beschreibungen anzuzeigen.
// Weitere Informationen finden Sie unter https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"name": "f0ckapp",
"request": "launch",
"type": "dart"
},
{
"name": "f0ckapp (profile mode)",
"request": "launch",
"type": "dart",
"flutterMode": "profile"
},
{
"name": "f0ckapp (release mode)",
"request": "launch",
"type": "dart",
"flutterMode": "release"
}
]
}

15
lib/api/fetchitem.dart Normal file
View File

@ -0,0 +1,15 @@
import 'package:f0ckapp/model/item.dart';
import 'dart:convert';
import 'package:http/http.dart' as http;
Future<Item> fetchItemFromApi(id) async {
final response = await http.get(Uri.parse('https://f0ck.dev/api/v2/item/$id'));
if(response.statusCode == 200) {
//List jsonresponse = json.decode(response.body)['rows'];
Map<String, dynamic> jsonresponse = json.decode(response.body)['rows'];
return Item.fromJson(jsonresponse);
} else {
throw Exception('failed to load feed');
}
}

View File

@ -1,11 +1,28 @@
import 'package:flutter/material.dart';
import 'package:f0ckapp/view/home.dart';
import 'package:f0ckapp/view/item.dart';
void main() {
/*void main() {
runApp(MaterialApp(
theme: ThemeData(
scaffoldBackgroundColor: const Color.fromARGB(255, 23, 23, 23)
),
home: const Home()
));
}*/
void main() async {
runApp(
MaterialApp(
debugShowCheckedModeBanner: false,
initialRoute: '/',
theme: ThemeData(
scaffoldBackgroundColor: const Color.fromARGB(255, 23, 23, 23)
),
routes: {
'/': (context) => const Home(),
'/detail': (context) => const ItemPage(id: 0),
}
),
);
}

View File

@ -2,18 +2,21 @@ class Item {
int id;
String mime;
int tagId;
String dest;
Item({
required this.id,
required this.mime,
required this.tagId
this.tagId = 0,
this.dest = ''
});
factory Item.fromJson(Map<String, dynamic> data) {
return Item(
id: data['id'],
mime: data['mime'],
tagId: data['tag_id']
tagId: data['tag_id'] ?? 0,
dest: data['dest'] ?? ''
);
}
}

View File

@ -1,6 +1,7 @@
import 'package:flutter/material.dart';
import 'package:f0ckapp/api/fetchdata.dart';
import 'package:f0ckapp/model/item.dart';
import 'package:f0ckapp/view/item.dart';
class Home extends StatefulWidget {
const Home({Key? key}) : super(key: key);
@ -19,6 +20,13 @@ class _HomeState extends State<Home> {
f0cks = fetchDataFromApi();
}
Future loadf0cks() {
setState(() {
f0cks = fetchDataFromApi();
});
return f0cks;
}
@override
Widget build(BuildContext context) {
return Scaffold(
@ -31,8 +39,14 @@ class _HomeState extends State<Home> {
body: FutureBuilder<List<Item>>(
future: f0cks,
builder: (context, snapshot) {
if(snapshot.hasData) {
return CustomScrollView(
if(!snapshot.hasData) {
return Text("${snapshot.error}");
}
return RefreshIndicator(
onRefresh: () {
return loadf0cks();
},
child: CustomScrollView(
shrinkWrap: true,
slivers: <Widget>[
SliverGrid(
@ -49,34 +63,41 @@ class _HomeState extends State<Home> {
case 2: mode = Colors.red; break;
default: mode = Colors.yellow; break;
}
return Stack(
children: <Widget>[
Image.network("https://f0ck.dev/t/${snapshot.data?[index].id}.webp"),
SizedBox(
child: Align(
alignment: FractionalOffset.bottomRight,
child: Padding(
padding: const EdgeInsets.only(bottom: 0, right: 0),
child: Icon(
Icons.square,
color: mode,
size: 15.0
return GestureDetector(
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => ItemPage(id: snapshot.data![index].id),
),
);
},
child: Stack(
children: <Widget>[
Image.network("https://f0ck.dev/t/${snapshot.data?[index].id}.webp"),
SizedBox(
child: Align(
alignment: FractionalOffset.bottomRight,
child: Padding(
padding: const EdgeInsets.only(bottom: 0, right: 0),
child: Icon(
Icons.square,
color: mode,
size: 15.0
),
),
),
),
)
]
)
]
)
);
},
childCount: snapshot.data?.length
)
),
]
);
} else if(snapshot.hasError) {
return Text("${snapshot.error}");
}
return const CircularProgressIndicator();
)
);
}
)
);

58
lib/view/item.dart Normal file
View File

@ -0,0 +1,58 @@
import 'package:flutter/material.dart';
import 'package:f0ckapp/model/item.dart';
import 'package:f0ckapp/api/fetchitem.dart';
class ItemPage extends StatefulWidget {
final int id;
const ItemPage({Key? key, required this.id }) : super(key: key);
@override
// ignore: library_private_types_in_public_api
_ItemPageState createState() => _ItemPageState();
}
class _ItemPageState extends State<ItemPage> with SingleTickerProviderStateMixin {
late final int id;
late Future<Item> f0ck;
@override
void initState() {
super.initState();
id = widget.id;
f0ck = fetchItemFromApi(id);
}
@override
Widget build(BuildContext context) {
return FutureBuilder<Item>(
future: f0ck,
builder: (context, snapshot) {
if(!snapshot.hasData) {
return const Center(child: CircularProgressIndicator());
}
final deviceSize = MediaQuery.of(context).size;
//final aspectRatio = widget.item.width / widget.item.height;
//final containerHeight = deviceSize.width / aspectRatio;
return RefreshIndicator(
onRefresh: () {
return fetchItemFromApi(id);
},
child: SingleChildScrollView(
physics: const AlwaysScrollableScrollPhysics(),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
SizedBox(
width: deviceSize.width,
height: 550,//containerHeight,
child: snapshot.data!.mime.startsWith('image') ? Image.network("https://f0ck.dev/b/${snapshot.data?.dest}") : const Text("no image"),
)
]
)
)
);
}
);
}
}