Skip to content

Commit 103de6d

Browse files
committed
refactor: upgrade everythign
1 parent 0137166 commit 103de6d

28 files changed

Lines changed: 560 additions & 370 deletions

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,3 +46,4 @@ app.*.map.json
4646
/android/app/release
4747
/coverage/lcov.info
4848
.direnv
49+
android/build/

.idx/dev.nix

Lines changed: 0 additions & 42 deletions
This file was deleted.

.metadata

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,27 @@
44
# This file should be version controlled and should not be manually edited.
55

66
version:
7-
revision: c860cba910319332564e1e9d470a17074c1f2dfd
8-
channel: stable
7+
revision: "nixpkgs000000000000000000000000000000000"
8+
channel: "stable"
99

1010
project_type: app
11+
12+
# Tracks metadata for the flutter migrate command
13+
migration:
14+
platforms:
15+
- platform: root
16+
create_revision: nixpkgs000000000000000000000000000000000
17+
base_revision: nixpkgs000000000000000000000000000000000
18+
- platform: android
19+
create_revision: nixpkgs000000000000000000000000000000000
20+
base_revision: nixpkgs000000000000000000000000000000000
21+
22+
# User provided section
23+
24+
# List of Local paths (relative to this file) that should be
25+
# ignored by the migrate tool.
26+
#
27+
# Files that are not part of the templates will be ignored by default.
28+
unmanaged_files:
29+
- 'lib/main.dart'
30+
- 'ios/Runner.xcodeproj/project.pbxproj'

AGENTS.md

Lines changed: 214 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,214 @@
1+
# Developer Guide for markdownr
2+
3+
This document provides guidelines for agentic coding agents working on this repository.
4+
5+
## Project Overview
6+
7+
markdownr is a Flutter Android app that converts URLs to Markdown format and allows sharing to other apps. It uses the readability algorithm to extract content from web pages.
8+
9+
## Tech Stack
10+
11+
- **Flutter**: 3.32Android only.0+ ()
12+
- **Dart**: 3.0.0+
13+
- **Key dependencies**: http, html2md, flutter_markdown_plus, share_plus, receive_sharing_intent, readability
14+
- **Testing**: flutter_test, mockito, build_runner
15+
- **Linting**: flutter_lints
16+
17+
## Build / Lint / Test Commands
18+
19+
### Running Tests
20+
21+
```bash
22+
# Run all tests
23+
flutter test
24+
25+
# Run a single test file
26+
flutter test test/converter_test.dart
27+
28+
# Run a specific test by name
29+
flutter test --name "convert should handle exceptions"
30+
```
31+
32+
### Linting & Formatting
33+
34+
```bash
35+
# Format code (required before committing)
36+
dart format --set-exit-if-changed .
37+
38+
# Run static analysis
39+
flutter analyze
40+
```
41+
42+
### Building
43+
44+
```bash
45+
# Build debug APK
46+
flutter build apk
47+
48+
# Build release APK
49+
flutter build apk --release
50+
51+
# Get dependencies
52+
flutter pub get
53+
```
54+
55+
### Code Generation
56+
57+
```bash
58+
# Generate mock classes (required after modifying mocks)
59+
dart run build_runner build
60+
```
61+
62+
### Taskfile Commands
63+
64+
The project includes a Taskfile.yaml with common tasks:
65+
66+
```bash
67+
# Run tests
68+
task test
69+
70+
# Run lint and format checks
71+
task lint
72+
73+
# Generate mocks
74+
task build-mocks
75+
```
76+
77+
## Code Style Guidelines
78+
79+
### General Conventions
80+
81+
- Follow Flutter/Dart best practices
82+
- Use `analysis_options.yaml` which includes `package:flutter_lints/flutter.yaml`
83+
- Enable strict null safety (Dart 3.0+)
84+
- Prefer immutability: use `const` constructors where possible
85+
86+
### Imports
87+
88+
Organize imports in the following order:
89+
1. Dart core libraries (`dart:io`, `dart:async`, etc.)
90+
2. Package imports (`package:flutter/...`)
91+
3. Relative imports (`package:markdownr/...`)
92+
93+
```dart
94+
import 'dart:async';
95+
96+
import 'package:flutter/material.dart';
97+
import 'package:flutter/services.dart';
98+
import 'package:markdownr/converter.dart';
99+
import 'package:markdownr/settings.dart';
100+
```
101+
102+
### Naming Conventions
103+
104+
- **Classes**: PascalCase (`Url2MdConverter`, `HomePage`)
105+
- **Functions/Methods**: camelCase (`convertPage`, `_buildAppBar`)
106+
- **Private members**: prefix with underscore (`_httpClient`, `_controller`)
107+
- **Constants**: camelCase or SCREAMING_SNAKE_CASE depending on context
108+
- **Files**: snake_case (`converter_test.dart`, `httpclient.dart`)
109+
110+
### Class Structure
111+
112+
```dart
113+
class MyClass {
114+
// Final fields first
115+
final String _someField;
116+
117+
// Constructor
118+
MyClass({required String someField}) : _someField = someField;
119+
120+
// Public methods
121+
Future<void> doSomething() async { }
122+
123+
// Private methods
124+
void _helperMethod() { }
125+
}
126+
```
127+
128+
### Error Handling
129+
130+
- Use try-catch blocks for operations that may fail
131+
- Show user-friendly error messages via notification service
132+
- Return sensible defaults on error (see `converter.dart:66-75`)
133+
134+
```dart
135+
try {
136+
var html = await _httpClient.getPage(url);
137+
// process...
138+
} catch (e) {
139+
_notificationService.showToast("$e");
140+
return defaultValue;
141+
}
142+
```
143+
144+
### Testing Conventions
145+
146+
- Test files: `test/<feature>_test.dart`
147+
- Use mockito for mocking dependencies
148+
- Generate mocks with `@GenerateNiceMocks` annotation
149+
- Run `dart run build_runner build` after creating/updating mocks
150+
- Group tests with `group()` and use `test()` for individual cases
151+
152+
```dart
153+
@GenerateNiceMocks([
154+
MockSpec<HttpClient>(),
155+
MockSpec<NotificationService>(),
156+
])
157+
import 'my_test.mocks.dart';
158+
159+
void main() {
160+
group('MyClass', () {
161+
late MockHttpClient mockHttpClient;
162+
late MyClass myClass;
163+
164+
setUp(() {
165+
mockHttpClient = MockHttpClient();
166+
myClass = MyClass(httpClient: mockHttpClient);
167+
});
168+
169+
test('should do something', () async {
170+
when(mockHttpClient.getPage(any)).thenAnswer((_) async => 'result');
171+
final result = await myClass.doSomething();
172+
expect(result, 'expected');
173+
});
174+
});
175+
}
176+
```
177+
178+
### Flutter-Specific Guidelines
179+
180+
- Use `const` for widgets and constructors when possible
181+
- Follow Flutter's widget composition patterns
182+
- Use `setState` for local state management (simple app)
183+
- Handle async operations in `initState` properly
184+
- Check `context.mounted` before using context in async callbacks
185+
186+
```dart
187+
// Good: Check mounted before using context
188+
Future.delayed(Duration.zero, () {
189+
if (context.mounted) {
190+
ScaffoldMessenger.of(context).showSnackBar(...);
191+
}
192+
});
193+
```
194+
195+
### Widget Build Methods
196+
197+
- Extract UI parts into private methods starting with `_build`
198+
- Keep `build()` method clean and readable
199+
- Use descriptive names: `_buildAppBar()`, `_buildUrlInput()`
200+
201+
## Project Structure
202+
203+
- `lib`: contains the flutter code of the app
204+
- `test`: contains the tests
205+
206+
## CI/CD
207+
208+
The project uses GitHub Actions to build, test and publish the application.
209+
210+
## Common Issues & Solutions
211+
212+
1. **Mocks not found**: Run `dart run build_runner build` to regenerate mocks
213+
2. **Lint errors**: Run `dart format . && flutter analyze` before committing
214+
3. **Missing dependencies**: Run `flutter pub get` after updating pubspec.yaml

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ This app has been made possible thanks ti these wonderful libraries:
3333
- `readability4J`
3434
- `receive_sharing_intent`
3535
- `share_plus`
36-
- `flutter_markdown`
36+
- `flutter_markdown_plus`
3737
- `http`
3838
- `shared_preferences`
3939
- `fluttertoast`

Taskfile.yaml

Lines changed: 33 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,46 @@
1-
version: '3'
1+
version: "3"
2+
3+
vars:
4+
PHONE_IP: 192.168.1.70
25

36
tasks:
7+
default:
8+
aliases: [help]
9+
desc: list all the tasks
10+
cmds:
11+
- task --list-all
12+
413
build-mocks:
14+
desc: Build test mocks
515
cmds:
616
- dart run build_runner build
717

818
test:
19+
desc: Run tests
920
cmds:
10-
- flutter test
21+
- flutter test --no-test-assets --coverage
22+
- flutter pub run test_cov_console
1123

1224
lint:
25+
desc: format and analyze the code
1326
cmds:
1427
- dart format --set-exit-if-changed .
1528
- flutter analyze
29+
30+
build:
31+
desc: build android apk
32+
cmds:
33+
- flutter build apk
34+
35+
adb-wifi:
36+
desc: set up adb connection via Wi-Fi. Make sure the phone is connected via USB.
37+
cmds:
38+
- adb tcpip ${PHONE_IP}
39+
# - adb connect ${PHONE_IP}
40+
# - echo "You can now disconnect the USB cable."
41+
42+
debug:
43+
desc: Debug the app on an adb connected phone
44+
cmds:
45+
# - adb connect ${PHONE_IP}
46+
- flutter run

android/.gitignore

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,10 @@ gradle-wrapper.jar
55
/gradlew.bat
66
/local.properties
77
GeneratedPluginRegistrant.java
8+
.cxx/
89

910
# Remember to never publicly share your keystore.
10-
# See https://flutter.dev/docs/deployment/android#reference-the-keystore-from-the-app
11+
# See https://flutter.dev/to/reference-keystore
1112
key.properties
1213
**/*.keystore
1314
**/*.jks

0 commit comments

Comments
 (0)