361 lines
10 KiB
Dart
361 lines
10 KiB
Dart
import 'dart:convert';
|
|
|
|
import 'package:badges/badges.dart';
|
|
import 'package:flutter/material.dart';
|
|
import 'package:flutter_markdown/flutter_markdown.dart';
|
|
import 'package:gitea_client/model/repository.dart';
|
|
import 'package:gitea_client/model/user.dart';
|
|
import 'package:gitea_client/service/gitea_service.dart';
|
|
import 'package:gitea_client/widget/code_page.dart';
|
|
|
|
import '../model/File.dart';
|
|
|
|
class RepoPage extends StatefulWidget {
|
|
final Repository repo;
|
|
final SavedUser user;
|
|
|
|
const RepoPage({Key? key, required this.repo, required this.user})
|
|
: super(key: key);
|
|
|
|
@override
|
|
_RepoPage createState() => _RepoPage();
|
|
}
|
|
|
|
class _RepoPage extends State<RepoPage> {
|
|
int _currentIndex = 0;
|
|
|
|
late final List _screens;
|
|
|
|
@override
|
|
void initState() {
|
|
_screens = [
|
|
RepoHome(
|
|
repo: widget.repo,
|
|
user: widget.user,
|
|
),
|
|
RepoFiles(
|
|
repo: widget.repo,
|
|
user: widget.user,
|
|
),
|
|
RepoIssues(
|
|
repo: widget.repo,
|
|
user: widget.user,
|
|
),
|
|
RepoPullRequests(
|
|
repo: widget.repo,
|
|
user: widget.user,
|
|
)
|
|
];
|
|
}
|
|
|
|
void _updateIndex(int value) {
|
|
setState(() {
|
|
_currentIndex = value;
|
|
});
|
|
}
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
return Scaffold(
|
|
appBar: AppBar(
|
|
title: Text(widget.repo.name),
|
|
),
|
|
body: _screens[_currentIndex],
|
|
bottomNavigationBar: BottomNavigationBar(
|
|
type: BottomNavigationBarType.fixed,
|
|
currentIndex: _currentIndex,
|
|
onTap: _updateIndex,
|
|
selectedItemColor: Colors.green[700],
|
|
selectedFontSize: 13,
|
|
unselectedFontSize: 13,
|
|
iconSize: 30,
|
|
items: [
|
|
const BottomNavigationBarItem(
|
|
label: "Home",
|
|
icon: Icon(Icons.home),
|
|
),
|
|
const BottomNavigationBarItem(
|
|
label: "Files",
|
|
icon: Icon(Icons.folder),
|
|
),
|
|
if (widget.repo.hasIssues!)
|
|
BottomNavigationBarItem(
|
|
label: "Issues",
|
|
icon: (widget.repo.openIssuesCount! > 0)
|
|
? Badge(
|
|
badgeContent:
|
|
Text(widget.repo.openIssuesCount!.toString()),
|
|
child: const Icon(Icons.error_outline),
|
|
)
|
|
: const Icon(Icons.error_outline),
|
|
),
|
|
if (widget.repo.hasPullRequests!)
|
|
BottomNavigationBarItem(
|
|
label: "Pull requests",
|
|
icon: (widget.repo.openPrCounter! > 0)
|
|
? Badge(
|
|
badgeContent: Text(widget.repo.openPrCounter!.toString()),
|
|
child: const Icon(Icons.mediation_rounded),
|
|
)
|
|
: const Icon(Icons.mediation_rounded),
|
|
),
|
|
],
|
|
),
|
|
);
|
|
}
|
|
}
|
|
|
|
class RepoHome extends StatefulWidget {
|
|
final Repository repo;
|
|
final SavedUser user;
|
|
|
|
const RepoHome({Key? key, required this.repo, required this.user})
|
|
: super(key: key);
|
|
|
|
@override
|
|
_RepoHome createState() => _RepoHome();
|
|
}
|
|
|
|
class _RepoHome extends State<RepoHome> {
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
final media = MediaQuery.of(context).size;
|
|
final padding = MediaQuery.of(context).viewPadding;
|
|
return Column(children: [
|
|
/*Text(
|
|
widget.repo.fullName!,
|
|
style: Theme.of(context).textTheme.headline3,
|
|
),*/
|
|
FutureBuilder<RepoFile>(
|
|
future: readmeRequest,
|
|
builder: (context, snapshot) {
|
|
if (snapshot.hasError) {
|
|
return Center(
|
|
child: Column(
|
|
children: [
|
|
Text("No Readme file found!",
|
|
style: Theme.of(context).textTheme.headline6),
|
|
],
|
|
),
|
|
);
|
|
} else if (snapshot.hasData) {
|
|
var file = snapshot.data!;
|
|
final content = utf8.decode(base64.decode(file.content!));
|
|
|
|
return Center(
|
|
child: SizedBox(
|
|
width: (media.width > 600)
|
|
? media.width * 0.6
|
|
: media.width * 0.9,
|
|
|
|
height: media.height - padding.top - padding.bottom -kToolbarHeight -kBottomNavigationBarHeight-30,
|
|
child: Column(
|
|
children: [
|
|
Expanded(child: Markdown(selectable: true, data: content)),
|
|
],
|
|
)),
|
|
);
|
|
} else {
|
|
return const Center(
|
|
child: CircularProgressIndicator(),
|
|
);
|
|
}
|
|
})
|
|
]);
|
|
}
|
|
|
|
Future<RepoFile>? readmeRequest;
|
|
late final GiteaService giteaService;
|
|
|
|
@override
|
|
void initState() {
|
|
giteaService = GiteaService(apiAccess: widget.user.apiAccess);
|
|
readmeRequest = giteaService.getFile(
|
|
widget.repo.owner.username!, widget.repo.name, "README.md");
|
|
}
|
|
}
|
|
|
|
class RepoFiles extends StatefulWidget {
|
|
final Repository repo;
|
|
final SavedUser user;
|
|
|
|
const RepoFiles({Key? key, required this.repo, required this.user})
|
|
: super(key: key);
|
|
|
|
@override
|
|
_RepoFiles createState() => _RepoFiles();
|
|
}
|
|
|
|
class _RepoFiles extends State<RepoFiles> {
|
|
String path = "/";
|
|
Future<List<RepoFile>>? readmeRequest;
|
|
late final GiteaService giteaService;
|
|
final _scrollController = ScrollController();
|
|
|
|
@override
|
|
void initState() {
|
|
giteaService = GiteaService(apiAccess: widget.user.apiAccess);
|
|
readmeRequest = giteaService.getFolder(
|
|
widget.repo.owner.username!, widget.repo.name, path);
|
|
}
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
return FutureBuilder<List<RepoFile>>(
|
|
future: readmeRequest,
|
|
builder: (context, snapshot) {
|
|
if (snapshot.hasError) {
|
|
return Center(
|
|
child: Column(
|
|
children: [
|
|
Text("No Readme file found!",
|
|
style: Theme.of(context).textTheme.headline6),
|
|
],
|
|
),
|
|
);
|
|
} else if (snapshot.hasData) {
|
|
var files = (path == "/")
|
|
? []
|
|
: [
|
|
RepoFile(
|
|
name: "..",
|
|
path: path,
|
|
sha: "",
|
|
type: "dir",
|
|
size: 0,
|
|
url: "",
|
|
htmlUrl: "",
|
|
gitUrl: "",
|
|
lLinks: Links(self: "", git: "", html: ""))
|
|
];
|
|
files.addAll(snapshot.data!);
|
|
|
|
return ListView.builder(
|
|
itemBuilder: (BuildContext context, int index) {
|
|
return FileListItem(
|
|
file: files[index],
|
|
onTap: () => {
|
|
if (files[index].type == "dir")
|
|
setState(() {
|
|
String prev = files[index].path.contains("/")
|
|
? files[index].path.substring(
|
|
0, files[index].path.lastIndexOf('/'))
|
|
: "/";
|
|
path = (files[index].name == "..")
|
|
? prev
|
|
: files[index].path;
|
|
readmeRequest = null;
|
|
readmeRequest = giteaService.getFolder(
|
|
widget.repo.owner.username!,
|
|
widget.repo.name,
|
|
path);
|
|
})
|
|
else
|
|
Navigator.of(context).pushNamed("/fileview",
|
|
arguments: CodePageData(
|
|
files[index].path,
|
|
widget.repo.name,
|
|
widget.repo.owner.username!,
|
|
widget.user))
|
|
});
|
|
},
|
|
itemCount: files.length,
|
|
controller: _scrollController,
|
|
);
|
|
} else {
|
|
return const Center(
|
|
child: CircularProgressIndicator(),
|
|
);
|
|
}
|
|
});
|
|
}
|
|
}
|
|
|
|
class FileListItem extends StatelessWidget {
|
|
final RepoFile file;
|
|
final Function onTap;
|
|
|
|
const FileListItem({Key? key, required this.file, required this.onTap})
|
|
: super(key: key);
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
return ListTile(
|
|
leading: (file.type == "file")
|
|
? const Icon(Icons.insert_drive_file_outlined)
|
|
: const Icon(Icons.folder_outlined),
|
|
title: Text(file.name),
|
|
onTap: () => {onTap()},
|
|
);
|
|
}
|
|
}
|
|
|
|
class RepoIssues extends StatefulWidget {
|
|
final Repository repo;
|
|
final SavedUser user;
|
|
|
|
const RepoIssues({Key? key, required this.repo, required this.user})
|
|
: super(key: key);
|
|
|
|
@override
|
|
_RepoIssues createState() => _RepoIssues();
|
|
}
|
|
|
|
class _RepoIssues extends State<RepoIssues> {
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
return DefaultTabController(
|
|
length: 2,
|
|
child:DefaultTabController(
|
|
length: 2,
|
|
child: Scaffold(
|
|
appBar: PreferredSize(
|
|
preferredSize: const Size.fromHeight(kToolbarHeight),
|
|
child: Container(
|
|
color: Colors.lightGreen,
|
|
child: SafeArea(
|
|
child: Column(
|
|
children: <Widget>[
|
|
Expanded(child: Container()),
|
|
const TabBar(
|
|
tabs: [Text("Open"), Text("Closed")],
|
|
),
|
|
],
|
|
),
|
|
),
|
|
),
|
|
),
|
|
body: TabBarView(
|
|
children: <Widget>[
|
|
Column(
|
|
children: const [Text("Lunches Page")],
|
|
),
|
|
Column(
|
|
children: const [ Text("Cart Page")],
|
|
)
|
|
],
|
|
),
|
|
),
|
|
),
|
|
);
|
|
}
|
|
}
|
|
|
|
class RepoPullRequests extends StatefulWidget {
|
|
final Repository repo;
|
|
final SavedUser user;
|
|
|
|
const RepoPullRequests({Key? key, required this.repo, required this.user})
|
|
: super(key: key);
|
|
|
|
@override
|
|
_RepoPullRequests createState() => _RepoPullRequests();
|
|
}
|
|
|
|
class _RepoPullRequests extends State<RepoPullRequests> {
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
// TODO: implement build
|
|
throw UnimplementedError();
|
|
}
|
|
}
|