small web feature initial

This commit is contained in:
Fabian Freund
2026-03-23 11:13:39 +01:00
parent 1e56bb3e3a
commit b9669635d9
61 changed files with 10455 additions and 233 deletions
@@ -0,0 +1,77 @@
/*
* Copyright (c) 2024-2026 Fabian Freund.
*
* This file is part of WebLibre
* (see https://weblibre.eu).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
class KagiCategoryDefinition {
final String slug;
final String label;
final String description;
final String emoji;
const KagiCategoryDefinition({
required this.slug,
required this.label,
required this.description,
required this.emoji,
});
}
class KagiCategories {
final Map<String, KagiCategoryDefinition> categories;
final Map<String, List<String>> groups;
final Map<String, String> remap;
const KagiCategories({
required this.categories,
required this.groups,
required this.remap,
});
factory KagiCategories.fromJson(Map<String, dynamic> json) {
final rawCategories = json['categories'] as Map<String, dynamic>;
final categories = rawCategories.map(
(slug, data) => MapEntry(
slug,
KagiCategoryDefinition(
slug: slug,
label: (data as Map<String, dynamic>)['label'] as String,
description: data['description'] as String,
emoji: data['emoji'] as String,
),
),
);
final rawGroups = json['groups'] as Map<String, dynamic>;
final groups = rawGroups.map(
(name, slugs) => MapEntry(
name,
(slugs as List<dynamic>).cast<String>(),
),
);
final rawRemap = json['remap'] as Map<String, dynamic>;
final remap = rawRemap.cast<String, String>();
return KagiCategories(
categories: categories,
groups: groups,
remap: remap,
);
}
}
@@ -0,0 +1,49 @@
/*
* Copyright (c) 2024-2026 Fabian Freund.
*
* This file is part of WebLibre
* (see https://weblibre.eu).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
import 'package:fast_equatable/fast_equatable.dart';
class KagiFeedEntry with FastEquatable {
final Uri url;
final String? title;
final String? author;
final String? summary;
final DateTime? publishedAt;
final List<String> categories;
KagiFeedEntry({
required this.url,
this.title,
this.author,
this.summary,
this.publishedAt,
this.categories = const [],
});
@override
List<Object?> get hashParameters => [
url,
title,
author,
summary,
publishedAt,
categories,
];
}
@@ -0,0 +1,49 @@
/*
* Copyright (c) 2024-2026 Fabian Freund.
*
* This file is part of WebLibre
* (see https://weblibre.eu).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
import 'package:flutter/material.dart';
enum KagiSmallWebMode {
web('Web', Icons.language, 'https://kagi.com/api/v1/smallweb/feed?nso'),
appreciated(
'Appreciated',
Icons.thumb_up_outlined,
'https://kagi.com/smallweb/appreciated',
),
videos(
'Videos',
Icons.play_circle_outline,
'https://kagi.com/api/v1/smallweb/feed?yt',
),
code('Code', Icons.code, 'https://kagi.com/api/v1/smallweb/feed?gh'),
comics(
'Comics',
Icons.auto_stories,
'https://kagi.com/api/v1/smallweb/feed?comic',
);
final String label;
final IconData icon;
final String feedUrlString;
const KagiSmallWebMode(this.label, this.icon, this.feedUrlString);
Uri get feedUrl => Uri.parse(feedUrlString);
}
@@ -0,0 +1,32 @@
/*
* Copyright (c) 2024-2026 Fabian Freund.
*
* This file is part of WebLibre
* (see https://weblibre.eu).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
import 'package:flutter/material.dart';
enum SmallWebSourceKind {
kagi('Kagi', Icons.travel_explore, 'Small Web by Kagi Search'),
wander('Wander', Icons.dns, 'Console-based web ring');
final String label;
final IconData icon;
final String description;
const SmallWebSourceKind(this.label, this.icon, this.description);
}
@@ -0,0 +1,21 @@
/*
* Copyright (c) 2024-2026 Fabian Freund.
*
* This file is part of WebLibre
* (see https://weblibre.eu).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
enum WanderConsoleSource { seed, manual, discovered }