Merge branch 'main' into resolve-issue-history-clear

This commit is contained in:
Ashita Prasad
2025-02-16 11:25:04 +05:30
committed by GitHub
10 changed files with 209 additions and 29 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 57 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 100 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 87 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 87 KiB

View File

@ -1,5 +1,14 @@
# Packaging API Dash
- [Windows](#windows)
- [macOS](#macos)
- [Linux Debian (.deb) & RPM (.rpm)](#linux-debian-deb--rpm-rpm)
- [Arch Linux (PKGBUILD)](#arch-linux-pkgbuild)
- [FlatHub (Flatpak)](#flathub-flatpak)
- [Homebrew](#homebrew)
- [Chocolatey](#chocolatey)
- [WinGet](#winget)
## Windows
[Packaging and Distributing Flutter Desktop Apps : Creating Windows .exe installer](https://medium.com/@fluttergems/packaging-and-distributing-flutter-desktop-apps-the-missing-guide-for-open-source-indie-0b468d5e9e70)
@ -22,11 +31,172 @@ TODO Instructions
## Homebrew
TODO Instructions
Homebrew Formula Submission
### 1. Prepare Tap Repository
```
# Create Homebrew tap
gh repo create homebrew-tap --public --clone
mkdir -p homebrew-tap/Formula
cd homebrew-tap
```
### 2. Package apidash
```
# Build macOS bundle
flutter build macos
# Create versioned tarball
tar -czvf apidash-v1.0.0.tar.gz \
-C build/macos/Build/Products/Release/ \
Apidash.app
# Generate SHA256 checksum
shasum -a 256 apidash-v1.0.0.tar.gz
```
### 3. Create Formula File
`Formula/apidash.rb`:
```
class Apidash < Formula
desc "Modern API dashboard for developers"
homepage "https://apidash.dev"
url "https://github.com/<user>/<repo>/releases/download/v1.0.0/apidash-v1.0.0.tar.gz"
sha256 "PASTE_YOUR_SHA256_HERE"
def install
prefix.install "Apidash.app"
bin.write_exec_script prefix/"Apidash.app/Contents/MacOS/Apidash"
end
test do
system "#{bin}/Apidash", "--version"
end
end
```
### 4. Local Validation
```
# Check formula syntax
brew audit --strict Formula/apidash.rb
# Test installation
brew install --build-from-source Formula/apidash.rb
# Verify execution
brew test apidash
```
### 5. Custom Tap Submission
```
# Commit formula to your tap repo
git add Formula/Apidash.rb
git commit -m "added apidash formula"
git push
# Create release for tarball
gh release create v1.0.0 apidash-v1.0.0.tar.gz
```
### 6. Installation
```
brew tap homebrew-tap/Formula
brew install apidash
```
## Chocolatey
TODO Instructions
### Step 1: Setup Skeleton
First step towards making a choco package is initializing a base.
The command `choco new -h` can teach you more about the `new` command, its usage, options, switches, and exit codes.
Run the following command to setup the base
```powershell
choco new --name="apidash" --version="0.3.0" maintainername="foss42" maintainerrepo="https://github.com/foss42/apidash" --built-in-template
```
![choco folder structure](images/choco_create_structure.png)
This creates the following folder structure
```
apidash
├── ReadMe.md
├── _TODO.txt
├── apidash.nuspec
└── tools
├── chocolateybeforemodify.ps1
├── chocolateyinstall.ps1
├── chocolateyuninstall.ps1
├── LICENSE.txt
└── VERIFICATION.txt
```
The files `ReadMe.md` and `_TODO.md` can be deleted before pushing.
The files of our main interest are `chocolateyinstall.ps1` and `apidash.nuspec`.
### Step 2: Editing `chocolateyinstall.ps1`
Take a look at `chocolateyinstall.ps1` file. There are many comments stating the use case of each line itself.
![chocolatelyinstall.ps1](images/choco_chocolateyinstall_ps1.png)
Comments can bre remoed using the following command.
```powershell
$f='apidash\tools\chocolateyinstall.ps1'
gc $f | ? {$_ -notmatch "^\s*#"} | % {$_ -replace '(^.*?)\s*? [^``]#.*','$1'} | Out-File $f+".~" -en utf8; mv -fo $f+".~" $f
```
Now our `chocolateyinstall.ps1` file is ready.
### Step 3: Editing `apidash.nuspec`
![final apidash.nuspec](images/choco_nuspec.png)
### Step 4: Build the package
All our files are ready, we just need to pack out files in a choco package with the extension `.nupkg`.
Run the following command from the root of your directory:
```powershell
choco pack
```
This command generates the `apidash.0.3.0.nupkg` file.
### Step 5: Test the Package Locally
Install the package locally using Chocolatey:
```powershell
choco install apidash -s .
```
Ensure the application installs correctly.
![Shell output](images/choco_shell_output.png)
### Step 6: Pre-Publishing - Update `LICENSE.txt` & `VERIFICATION.txt`
Update `LICENSE.txt` with the actual **LICENSE **and `VERIFICATION.txt` accordingly.
### Step 7: Publish the Package (Optional)
To share the package, you can push it to a Chocolatey repository. For the official Chocolatey Community Repository, follow these steps:
1. Create an account on the Chocolatey Community.
2. Get an API key by navigating to your profile.
3. Use the following command to push your package:
```powershell
choco push apidash.0.3.0.nupkg --source="https://push.chocolatey.org/" --api-key="YOUR_API_KEY"
```
## WinGet

View File

@ -25,14 +25,11 @@ final requestSequenceProvider = StateProvider<List<String>>((ref) {
return ids ?? [];
});
final httpClientManager = HttpClientManager();
final StateNotifierProvider<CollectionStateNotifier, Map<String, RequestModel>?>
collectionStateNotifierProvider =
StateNotifierProvider((ref) => CollectionStateNotifier(
ref,
hiveHandler,
httpClientManager,
));
class CollectionStateNotifier
@ -40,7 +37,6 @@ class CollectionStateNotifier
CollectionStateNotifier(
this.ref,
this.hiveHandler,
this.httpClientManager,
) : super(null) {
var status = loadData();
Future.microtask(() {
@ -57,7 +53,6 @@ class CollectionStateNotifier
final Ref ref;
final HiveHandler hiveHandler;
final baseHttpResponseModel = const HttpResponseModel();
final HttpClientManager httpClientManager;
bool hasId(String id) => state?.keys.contains(id) ?? false;
@ -117,6 +112,7 @@ class CollectionStateNotifier
final rId = id ?? ref.read(selectedIdStateProvider);
var itemIds = ref.read(requestSequenceProvider);
int idx = itemIds.indexOf(rId!);
cancelHttpRequest(rId);
itemIds.remove(rId);
ref.read(requestSequenceProvider.notifier).state = [...itemIds];
@ -293,7 +289,7 @@ class CollectionStateNotifier
state = map;
bool noSSL = ref.read(settingsProvider).isSSLDisabled;
(HttpResponse?, Duration?, String?)? responseRec = await request(
var responseRec = await sendHttpRequest(
requestId,
apiType,
substitutedHttpRequestModel,
@ -349,7 +345,7 @@ class CollectionStateNotifier
void cancelRequest() {
final id = ref.read(selectedIdStateProvider);
httpClientManager.cancelRequest(id);
cancelHttpRequest(id);
unsave();
}

View File

@ -89,4 +89,11 @@ class HistoryMetaStateNotifier
await hiveHandler.setHistoryRequest(id, model.toJson());
await loadHistoryRequest(id);
}
Future<void> clearAllHistory() async {
await hiveHandler.clearAllHistory();
ref.read(selectedHistoryIdStateProvider.notifier).state = null;
ref.read(selectedHistoryRequestModelProvider.notifier).state = null;
loadHistoryMetas();
}
}

View File

@ -1,10 +1,9 @@
import 'package:apidash/services/services.dart';
import 'package:apidash_design_system/apidash_design_system.dart';
import 'package:flutter/material.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:apidash_design_system/apidash_design_system.dart';
import 'package:apidash/providers/providers.dart';
import 'package:apidash/widgets/widgets.dart';
import 'package:apidash/consts.dart';
import '../../../consts.dart';
class HistorySidebarHeader extends ConsumerWidget {
const HistorySidebarHeader({super.key});
@ -23,12 +22,12 @@ class HistorySidebarHeader extends ConsumerWidget {
),
const Spacer(),
ADIconButton(
icon: Icons.delete_forever,
iconSize: kButtonIconSizeLarge,
tooltip: "Clear History",
color: Theme.of(context).brightness == Brightness.dark
? kColorDarkDanger
: kColorLightDanger,
icon: Icons.delete_forever,
iconSize: kButtonIconSizeLarge,
tooltip: "Clear History",
color: Theme.of(context).brightness == Brightness.dark
? kColorDarkDanger
: kColorLightDanger,
onPressed: () {
showDialog(
context: context,
@ -43,7 +42,9 @@ class HistorySidebarHeader extends ConsumerWidget {
TextButton(
onPressed: () async {
try {
await hiveHandler.clearAllHistory(ref); // ✅ Pass `ref` here
await ref
.read(historyMetaStateNotifier.notifier)
.clearAllHistory();
if (context.mounted) {
Navigator.pop(context);

View File

@ -10,15 +10,16 @@ import 'http_client_manager.dart';
typedef HttpResponse = http.Response;
Future<(HttpResponse?, Duration?, String?)> request(
final httpClientManager = HttpClientManager();
Future<(HttpResponse?, Duration?, String?)> sendHttpRequest(
String requestId,
APIType apiType,
HttpRequestModel requestModel, {
SupportedUriSchemes defaultUriScheme = kDefaultUriScheme,
bool noSSL = false,
}) async {
final clientManager = HttpClientManager();
final client = clientManager.createClient(requestId, noSSL: noSSL);
final client = httpClientManager.createClient(requestId, noSSL: noSSL);
(Uri?, String?) uriRec = getValidRequestUri(
requestModel.url,
@ -123,14 +124,19 @@ Future<(HttpResponse?, Duration?, String?)> request(
stopwatch.stop();
return (response, stopwatch.elapsed, null);
} catch (e) {
if (clientManager.wasRequestCancelled(requestId)) {
if (httpClientManager.wasRequestCancelled(requestId)) {
return (null, null, kMsgRequestCancelled);
}
return (null, null, e.toString());
} finally {
clientManager.closeClient(requestId);
httpClientManager.closeClient(requestId);
}
} else {
return (null, null, uriRec.$2);
}
}
}
void cancelHttpRequest(String? requestId) {
httpClientManager.cancelRequest(requestId);
}

View File

@ -14,7 +14,7 @@ void main() {
});
test('Testing fromResponse', () async {
(HttpResponse?, Duration?, String?)? responseRec = await request(
var responseRec = await sendHttpRequest(
requestModelGet1.id,
requestModelGet1.apiType,
requestModelGet1.httpRequestModel!,
@ -32,7 +32,7 @@ void main() {
});
test('Testing fromResponse for contentType not Json', () async {
(HttpResponse?, Duration?, String?)? responseRec = await request(
var responseRec = await sendHttpRequest(
requestModelGet13.id,
requestModelGet1.apiType,
requestModelGet13.httpRequestModel!,
@ -48,7 +48,7 @@ void main() {
});
test('Testing fromResponse for Bad SSL with certificate check', () async {
(HttpResponse?, Duration?, String?)? responseRec = await request(
var responseRec = await sendHttpRequest(
requestModelGetBadSSL.id,
requestModelGet1.apiType,
requestModelGetBadSSL.httpRequestModel!,
@ -60,7 +60,7 @@ void main() {
});
test('Testing fromResponse for Bad SSL with no certificate check', () async {
(HttpResponse?, Duration?, String?)? responseRec = await request(
var responseRec = await sendHttpRequest(
requestModelGetBadSSL.id,
requestModelGet1.apiType,
requestModelGetBadSSL.httpRequestModel!,