Merge branch 'feature--flutter-support' of github.com:appwrite/appwrite into 0.6

This commit is contained in:
Eldad Fux
2020-05-01 10:59:54 +03:00
110 changed files with 2374 additions and 184 deletions
+5
View File
@@ -2,6 +2,7 @@
## Features
* Added support for Flutter iOS & Android apps
* New locale for Khmer
* Added TypeScript type hinting to the JS SDK (@zevektor)
@@ -10,6 +11,10 @@
* Updated all the REST API query params to be in camelCase
* Normalized locale phone codes response body
## Bug Fixes
* Fixed project users logout button
# Version 0.5.3 (PRE-RELEASE)
## Bug Fixes
+10 -10
View File
@@ -16,6 +16,7 @@ use Appwrite\Database\Database;
use Appwrite\Database\Document;
use Appwrite\Database\Validator\Authorization;
use Appwrite\Event\Event;
use Appwrite\Network\Validators\Origin;
/*
* Configuration files
@@ -51,7 +52,7 @@ $clients = array_unique(array_merge($clientsConsole, array_map(function ($node)
return false;
}))));
$utopia->init(function () use ($utopia, $request, $response, &$user, $project, $roles, $webhook, $audit, $usage, $clients) {
$utopia->init(function () use ($utopia, $request, $response, &$user, $project, $console, $roles, $webhook, $audit, $usage, $clients) {
$route = $utopia->match($request);
@@ -96,16 +97,15 @@ $utopia->init(function () use ($utopia, $request, $response, &$user, $project, $
* Adding Appwrite API domains to allow XDOMAIN communication
* Skip this check for non-web platforms which are not requiredto send an origin header
*/
$origin = parse_url($request->getServer('HTTP_ORIGIN', $request->getServer('HTTP_REFERER', '')), PHP_URL_HOST);
if (!empty($origin)
&& !in_array($origin, $clients)
&& in_array($request->getMethod(), [Request::METHOD_POST, Request::METHOD_PUT, Request::METHOD_PATCH, Request::METHOD_DELETE])
&& empty($request->getHeader('X-Appwrite-Key', ''))
) {
throw new Exception('Access from this client host is forbidden', 403);
}
$origin = $request->getServer('HTTP_ORIGIN', $request->getServer('HTTP_REFERER', ''));
$originValidator = new Origin(array_merge($project->getAttribute('platforms', []), $console->getAttribute('platforms', [])));
if(!$originValidator->isValid($origin)
&& in_array($request->getMethod(), [Request::METHOD_POST, Request::METHOD_PUT, Request::METHOD_PATCH, Request::METHOD_DELETE])
&& empty($request->getHeader('X-Appwrite-Key', ''))) {
throw new Exception($originValidator->getDescription(), 403);
}
/*
* ACL Check
*/
+2 -2
View File
@@ -124,13 +124,13 @@ return [
'key' => APP_PLATFORM_FLUTTER,
'name' => 'Flutter',
'description' => 'Client libraries for integrating with '.APP_NAME.' to build cross-platform Flutter applications. Read the [getting started for Flutter](/docs/getting-started-for-flutter) tutorial to start building your first Flutter application.',
'enabled' => false,
'enabled' => true,
'beta' => true,
'languages' => [
[
'key' => 'dart',
'name' => 'Dart',
'version' => '0.0.8',
'version' => '0.1.1',
'url' => 'https://github.com/appwrite/sdk-for-dart',
'enabled' => true,
'beta' => true,
+1 -1
View File
@@ -356,7 +356,7 @@ $utopia->get('/v1/avatars/qr')
->desc('Get QR Code')
->param('text', '', function () { return new Text(512); }, 'Plain text to be converted to QR code image.')
->param('size', 400, function () { return new Range(0, 1000); }, 'QR code size. Pass an integer between 0 to 1000. Defaults to 400.', true)
->param('margin', 1, function () { return new Range(0, 10); }, 'Margin From Edge. Pass an integer between 0 to 10. Defaults to 1.', true)
->param('margin', 1, function () { return new Range(0, 10); }, 'Margin from edge. Pass an integer between 0 to 10. Defaults to 1.', true)
->param('download', 0, function () { return new Range(0, 1); }, 'Return resulting image with \'Content-Disposition: attachment \' headers for the browser to start downloading it. Pass 0 for no header, or 1 for otherwise. Default value is set to 0.', true)
->label('scope', 'avatars.read')
->label('sdk.platform', [APP_PLATFORM_CLIENT, APP_PLATFORM_SERVER])
+1 -1
View File
@@ -1057,7 +1057,7 @@ $utopia->post('/v1/projects/:projectId/platforms')
->label('sdk.namespace', 'projects')
->label('sdk.method', 'createPlatform')
->param('projectId', null, function () { return new UID(); }, 'Project unique ID.')
->param('type', null, function () { return new WhiteList(['web', 'ios', 'android', 'unity']); }, 'Platform type.')
->param('type', null, function () { return new WhiteList(['web', 'flutter-ios', 'flutter-android', 'ios', 'android', 'unity']); }, 'Platform type.')
->param('name', null, function () { return new Text(256); }, 'Platform name.')
->param('key', '', function () { return new Text(256); }, 'Package name for android or bundle ID for iOS.', true)
->param('store', '', function () { return new Text(256); }, 'App store or Google Play store ID.', true)
-1
View File
@@ -4,7 +4,6 @@
![Version](https://img.shields.io/badge/api%20version-0.5.3-blue.svg?v=1)
![Appwrite](https://appwrite.io/images/github.png)
## Installation
+5
View File
@@ -0,0 +1,5 @@
# This is a generated file; do not edit or check into version control.
flutter_web_auth=/Users/eldadfux/.pub-cache/hosted/pub.dartlang.org/flutter_web_auth-0.1.3/
package_info=/Users/eldadfux/.pub-cache/hosted/pub.dartlang.org/package_info-0.4.0+16/
path_provider=/Users/eldadfux/.pub-cache/hosted/pub.dartlang.org/path_provider-1.6.5/
path_provider_macos=/Users/eldadfux/.pub-cache/hosted/pub.dartlang.org/path_provider_macos-0.0.4/
@@ -0,0 +1 @@
{"_info":"// This is a generated file; do not edit or check into version control.","dependencyGraph":[{"name":"flutter_web_auth","dependencies":[]},{"name":"package_info","dependencies":[]},{"name":"path_provider","dependencies":["path_provider_macos"]},{"name":"path_provider_macos","dependencies":[]}]}
+29
View File
@@ -1,3 +1,32 @@
## 0.1.1
- Updated flutter_web_auth version
## 0.1.0
- Added examples file
- Some minor style fixes
## 0.0.14
- Using MultipartFile for file uploads
## 0.0.13
- Fix for file upload method
## 0.0.12
- Added file upload support for storage service
## 0.0.11
- Added integration with web auth plugin to support Appwrite OAuth API
## 0.0.9
- Updated deafult params
## 0.0.8
- Fixed compilation error in Client class
+1 -2
View File
@@ -9,7 +9,6 @@
![Appwrite](https://appwrite.io/images/github.png)
## Installation
@@ -18,7 +17,7 @@ Add this to your package's `pubspec.yaml` file:
```yml
dependencies:
appwrite: ^0.0.8
appwrite: ^0.1.1
```
You can install packages from the command line:
@@ -0,0 +1,20 @@
import 'package:appwrite/appwrite.dart';
// Init SDK
Client client = Client();
Account account = Account(client);
client
.setProject('5df5acd0d48c2') // Your project ID
;
Future result = account.createOAuth2Session(
provider: 'bitbucket',
);
result
.then((response) {
print(response);
}).catchError((error) {
print(error);
});
@@ -0,0 +1,21 @@
import 'package:appwrite/appwrite.dart';
// Init SDK
Client client = Client();
Account account = Account(client);
client
.setProject('5df5acd0d48c2') // Your project ID
;
Future result = account.createRecovery(
email: 'email@example.com',
url: 'https://example.com',
);
result
.then((response) {
print(response);
}).catchError((error) {
print(error);
});
@@ -0,0 +1,21 @@
import 'package:appwrite/appwrite.dart';
// Init SDK
Client client = Client();
Account account = Account(client);
client
.setProject('5df5acd0d48c2') // Your project ID
;
Future result = account.createSession(
email: 'email@example.com',
password: 'password',
);
result
.then((response) {
print(response);
}).catchError((error) {
print(error);
});
@@ -0,0 +1,20 @@
import 'package:appwrite/appwrite.dart';
// Init SDK
Client client = Client();
Account account = Account(client);
client
.setProject('5df5acd0d48c2') // Your project ID
;
Future result = account.createVerification(
url: 'https://example.com',
);
result
.then((response) {
print(response);
}).catchError((error) {
print(error);
});
@@ -0,0 +1,21 @@
import 'package:appwrite/appwrite.dart';
// Init SDK
Client client = Client();
Account account = Account(client);
client
.setProject('5df5acd0d48c2') // Your project ID
;
Future result = account.create(
email: 'email@example.com',
password: 'password',
);
result
.then((response) {
print(response);
}).catchError((error) {
print(error);
});
@@ -0,0 +1,20 @@
import 'package:appwrite/appwrite.dart';
// Init SDK
Client client = Client();
Account account = Account(client);
client
.setProject('5df5acd0d48c2') // Your project ID
;
Future result = account.deleteSession(
sessionId: '[SESSION_ID]',
);
result
.then((response) {
print(response);
}).catchError((error) {
print(error);
});
@@ -0,0 +1,18 @@
import 'package:appwrite/appwrite.dart';
// Init SDK
Client client = Client();
Account account = Account(client);
client
.setProject('5df5acd0d48c2') // Your project ID
;
Future result = account.deleteSessions();
result
.then((response) {
print(response);
}).catchError((error) {
print(error);
});
@@ -0,0 +1,18 @@
import 'package:appwrite/appwrite.dart';
// Init SDK
Client client = Client();
Account account = Account(client);
client
.setProject('5df5acd0d48c2') // Your project ID
;
Future result = account.delete();
result
.then((response) {
print(response);
}).catchError((error) {
print(error);
});
@@ -0,0 +1,18 @@
import 'package:appwrite/appwrite.dart';
// Init SDK
Client client = Client();
Account account = Account(client);
client
.setProject('5df5acd0d48c2') // Your project ID
;
Future result = account.getLogs();
result
.then((response) {
print(response);
}).catchError((error) {
print(error);
});
@@ -0,0 +1,18 @@
import 'package:appwrite/appwrite.dart';
// Init SDK
Client client = Client();
Account account = Account(client);
client
.setProject('5df5acd0d48c2') // Your project ID
;
Future result = account.getPrefs();
result
.then((response) {
print(response);
}).catchError((error) {
print(error);
});
@@ -0,0 +1,18 @@
import 'package:appwrite/appwrite.dart';
// Init SDK
Client client = Client();
Account account = Account(client);
client
.setProject('5df5acd0d48c2') // Your project ID
;
Future result = account.getSessions();
result
.then((response) {
print(response);
}).catchError((error) {
print(error);
});
@@ -0,0 +1,18 @@
import 'package:appwrite/appwrite.dart';
// Init SDK
Client client = Client();
Account account = Account(client);
client
.setProject('5df5acd0d48c2') // Your project ID
;
Future result = account.get();
result
.then((response) {
print(response);
}).catchError((error) {
print(error);
});
@@ -0,0 +1,21 @@
import 'package:appwrite/appwrite.dart';
// Init SDK
Client client = Client();
Account account = Account(client);
client
.setProject('5df5acd0d48c2') // Your project ID
;
Future result = account.updateEmail(
email: 'email@example.com',
password: 'password',
);
result
.then((response) {
print(response);
}).catchError((error) {
print(error);
});
@@ -0,0 +1,20 @@
import 'package:appwrite/appwrite.dart';
// Init SDK
Client client = Client();
Account account = Account(client);
client
.setProject('5df5acd0d48c2') // Your project ID
;
Future result = account.updateName(
name: '[NAME]',
);
result
.then((response) {
print(response);
}).catchError((error) {
print(error);
});
@@ -0,0 +1,21 @@
import 'package:appwrite/appwrite.dart';
// Init SDK
Client client = Client();
Account account = Account(client);
client
.setProject('5df5acd0d48c2') // Your project ID
;
Future result = account.updatePassword(
password: 'password',
oldPassword: 'password',
);
result
.then((response) {
print(response);
}).catchError((error) {
print(error);
});
@@ -0,0 +1,20 @@
import 'package:appwrite/appwrite.dart';
// Init SDK
Client client = Client();
Account account = Account(client);
client
.setProject('5df5acd0d48c2') // Your project ID
;
Future result = account.updatePrefs(
prefs: {},
);
result
.then((response) {
print(response);
}).catchError((error) {
print(error);
});
@@ -0,0 +1,23 @@
import 'package:appwrite/appwrite.dart';
// Init SDK
Client client = Client();
Account account = Account(client);
client
.setProject('5df5acd0d48c2') // Your project ID
;
Future result = account.updateRecovery(
userId: '[USER_ID]',
secret: '[SECRET]',
passwordA: 'password',
passwordB: 'password',
);
result
.then((response) {
print(response);
}).catchError((error) {
print(error);
});
@@ -0,0 +1,21 @@
import 'package:appwrite/appwrite.dart';
// Init SDK
Client client = Client();
Account account = Account(client);
client
.setProject('5df5acd0d48c2') // Your project ID
;
Future result = account.updateVerification(
userId: '[USER_ID]',
secret: '[SECRET]',
);
result
.then((response) {
print(response);
}).catchError((error) {
print(error);
});
@@ -0,0 +1,20 @@
import 'package:appwrite/appwrite.dart';
// Init SDK
Client client = Client();
Avatars avatars = Avatars(client);
client
.setProject('5df5acd0d48c2') // Your project ID
;
Future result = avatars.getBrowser(
code: 'aa',
);
result
.then((response) {
print(response);
}).catchError((error) {
print(error);
});
@@ -0,0 +1,20 @@
import 'package:appwrite/appwrite.dart';
// Init SDK
Client client = Client();
Avatars avatars = Avatars(client);
client
.setProject('5df5acd0d48c2') // Your project ID
;
Future result = avatars.getCreditCard(
code: 'amex',
);
result
.then((response) {
print(response);
}).catchError((error) {
print(error);
});
@@ -0,0 +1,20 @@
import 'package:appwrite/appwrite.dart';
// Init SDK
Client client = Client();
Avatars avatars = Avatars(client);
client
.setProject('5df5acd0d48c2') // Your project ID
;
Future result = avatars.getFavicon(
url: 'https://example.com',
);
result
.then((response) {
print(response);
}).catchError((error) {
print(error);
});
@@ -0,0 +1,20 @@
import 'package:appwrite/appwrite.dart';
// Init SDK
Client client = Client();
Avatars avatars = Avatars(client);
client
.setProject('5df5acd0d48c2') // Your project ID
;
Future result = avatars.getFlag(
code: 'af',
);
result
.then((response) {
print(response);
}).catchError((error) {
print(error);
});
@@ -0,0 +1,20 @@
import 'package:appwrite/appwrite.dart';
// Init SDK
Client client = Client();
Avatars avatars = Avatars(client);
client
.setProject('5df5acd0d48c2') // Your project ID
;
Future result = avatars.getImage(
url: 'https://example.com',
);
result
.then((response) {
print(response);
}).catchError((error) {
print(error);
});
@@ -0,0 +1,20 @@
import 'package:appwrite/appwrite.dart';
// Init SDK
Client client = Client();
Avatars avatars = Avatars(client);
client
.setProject('5df5acd0d48c2') // Your project ID
;
Future result = avatars.getQR(
text: '[TEXT]',
);
result
.then((response) {
print(response);
}).catchError((error) {
print(error);
});
@@ -0,0 +1,23 @@
import 'package:appwrite/appwrite.dart';
// Init SDK
Client client = Client();
Database database = Database(client);
client
.setProject('5df5acd0d48c2') // Your project ID
;
Future result = database.createDocument(
collectionId: '[COLLECTION_ID]',
data: {},
read: [],
write: [],
);
result
.then((response) {
print(response);
}).catchError((error) {
print(error);
});
@@ -0,0 +1,21 @@
import 'package:appwrite/appwrite.dart';
// Init SDK
Client client = Client();
Database database = Database(client);
client
.setProject('5df5acd0d48c2') // Your project ID
;
Future result = database.deleteDocument(
collectionId: '[COLLECTION_ID]',
documentId: '[DOCUMENT_ID]',
);
result
.then((response) {
print(response);
}).catchError((error) {
print(error);
});
@@ -0,0 +1,21 @@
import 'package:appwrite/appwrite.dart';
// Init SDK
Client client = Client();
Database database = Database(client);
client
.setProject('5df5acd0d48c2') // Your project ID
;
Future result = database.getDocument(
collectionId: '[COLLECTION_ID]',
documentId: '[DOCUMENT_ID]',
);
result
.then((response) {
print(response);
}).catchError((error) {
print(error);
});
@@ -0,0 +1,20 @@
import 'package:appwrite/appwrite.dart';
// Init SDK
Client client = Client();
Database database = Database(client);
client
.setProject('5df5acd0d48c2') // Your project ID
;
Future result = database.listDocuments(
collectionId: '[COLLECTION_ID]',
);
result
.then((response) {
print(response);
}).catchError((error) {
print(error);
});
@@ -0,0 +1,24 @@
import 'package:appwrite/appwrite.dart';
// Init SDK
Client client = Client();
Database database = Database(client);
client
.setProject('5df5acd0d48c2') // Your project ID
;
Future result = database.updateDocument(
collectionId: '[COLLECTION_ID]',
documentId: '[DOCUMENT_ID]',
data: {},
read: [],
write: [],
);
result
.then((response) {
print(response);
}).catchError((error) {
print(error);
});
@@ -0,0 +1,18 @@
import 'package:appwrite/appwrite.dart';
// Init SDK
Client client = Client();
Locale locale = Locale(client);
client
.setProject('5df5acd0d48c2') // Your project ID
;
Future result = locale.getContinents();
result
.then((response) {
print(response);
}).catchError((error) {
print(error);
});
@@ -0,0 +1,18 @@
import 'package:appwrite/appwrite.dart';
// Init SDK
Client client = Client();
Locale locale = Locale(client);
client
.setProject('5df5acd0d48c2') // Your project ID
;
Future result = locale.getCountriesEU();
result
.then((response) {
print(response);
}).catchError((error) {
print(error);
});
@@ -0,0 +1,18 @@
import 'package:appwrite/appwrite.dart';
// Init SDK
Client client = Client();
Locale locale = Locale(client);
client
.setProject('5df5acd0d48c2') // Your project ID
;
Future result = locale.getCountriesPhones();
result
.then((response) {
print(response);
}).catchError((error) {
print(error);
});
@@ -0,0 +1,18 @@
import 'package:appwrite/appwrite.dart';
// Init SDK
Client client = Client();
Locale locale = Locale(client);
client
.setProject('5df5acd0d48c2') // Your project ID
;
Future result = locale.getCountries();
result
.then((response) {
print(response);
}).catchError((error) {
print(error);
});
@@ -0,0 +1,18 @@
import 'package:appwrite/appwrite.dart';
// Init SDK
Client client = Client();
Locale locale = Locale(client);
client
.setProject('5df5acd0d48c2') // Your project ID
;
Future result = locale.getCurrencies();
result
.then((response) {
print(response);
}).catchError((error) {
print(error);
});
@@ -0,0 +1,18 @@
import 'package:appwrite/appwrite.dart';
// Init SDK
Client client = Client();
Locale locale = Locale(client);
client
.setProject('5df5acd0d48c2') // Your project ID
;
Future result = locale.get();
result
.then((response) {
print(response);
}).catchError((error) {
print(error);
});
@@ -0,0 +1,23 @@
import 'dart:io';
import 'package:appwrite/appwrite.dart';
// Init SDK
Client client = Client();
Storage storage = Storage(client);
client
.setProject('5df5acd0d48c2') // Your project ID
;
Future result = storage.createFile(
file: await MultipartFile.fromFile('./path-to-files/image.jpg', 'image.jpg'),
read: [],
write: [],
);
result
.then((response) {
print(response);
}).catchError((error) {
print(error);
});
@@ -0,0 +1,20 @@
import 'package:appwrite/appwrite.dart';
// Init SDK
Client client = Client();
Storage storage = Storage(client);
client
.setProject('5df5acd0d48c2') // Your project ID
;
Future result = storage.deleteFile(
fileId: '[FILE_ID]',
);
result
.then((response) {
print(response);
}).catchError((error) {
print(error);
});
@@ -0,0 +1,15 @@
import 'package:appwrite/appwrite.dart';
// Init SDK
Client client = Client();
Storage storage = Storage(client);
client
.setProject('5df5acd0d48c2') // Your project ID
;
String result = storage.getFileDownload(
fileId: '[FILE_ID]',
);
print(result); // Resource URL string
@@ -0,0 +1,15 @@
import 'package:appwrite/appwrite.dart';
// Init SDK
Client client = Client();
Storage storage = Storage(client);
client
.setProject('5df5acd0d48c2') // Your project ID
;
String result = storage.getFilePreview(
fileId: '[FILE_ID]',
);
print(result); // Resource URL string
@@ -0,0 +1,15 @@
import 'package:appwrite/appwrite.dart';
// Init SDK
Client client = Client();
Storage storage = Storage(client);
client
.setProject('5df5acd0d48c2') // Your project ID
;
String result = storage.getFileView(
fileId: '[FILE_ID]',
);
print(result); // Resource URL string
@@ -0,0 +1,20 @@
import 'package:appwrite/appwrite.dart';
// Init SDK
Client client = Client();
Storage storage = Storage(client);
client
.setProject('5df5acd0d48c2') // Your project ID
;
Future result = storage.getFile(
fileId: '[FILE_ID]',
);
result
.then((response) {
print(response);
}).catchError((error) {
print(error);
});
@@ -0,0 +1,19 @@
import 'package:appwrite/appwrite.dart';
// Init SDK
Client client = Client();
Storage storage = Storage(client);
client
.setProject('5df5acd0d48c2') // Your project ID
;
Future result = storage.listFiles(
);
result
.then((response) {
print(response);
}).catchError((error) {
print(error);
});
@@ -0,0 +1,22 @@
import 'package:appwrite/appwrite.dart';
// Init SDK
Client client = Client();
Storage storage = Storage(client);
client
.setProject('5df5acd0d48c2') // Your project ID
;
Future result = storage.updateFile(
fileId: '[FILE_ID]',
read: [],
write: [],
);
result
.then((response) {
print(response);
}).catchError((error) {
print(error);
});
@@ -0,0 +1,23 @@
import 'package:appwrite/appwrite.dart';
// Init SDK
Client client = Client();
Teams teams = Teams(client);
client
.setProject('5df5acd0d48c2') // Your project ID
;
Future result = teams.createMembership(
teamId: '[TEAM_ID]',
email: 'email@example.com',
roles: [],
url: 'https://example.com',
);
result
.then((response) {
print(response);
}).catchError((error) {
print(error);
});
@@ -0,0 +1,20 @@
import 'package:appwrite/appwrite.dart';
// Init SDK
Client client = Client();
Teams teams = Teams(client);
client
.setProject('5df5acd0d48c2') // Your project ID
;
Future result = teams.create(
name: '[NAME]',
);
result
.then((response) {
print(response);
}).catchError((error) {
print(error);
});
@@ -0,0 +1,21 @@
import 'package:appwrite/appwrite.dart';
// Init SDK
Client client = Client();
Teams teams = Teams(client);
client
.setProject('5df5acd0d48c2') // Your project ID
;
Future result = teams.deleteMembership(
teamId: '[TEAM_ID]',
inviteId: '[INVITE_ID]',
);
result
.then((response) {
print(response);
}).catchError((error) {
print(error);
});
@@ -0,0 +1,20 @@
import 'package:appwrite/appwrite.dart';
// Init SDK
Client client = Client();
Teams teams = Teams(client);
client
.setProject('5df5acd0d48c2') // Your project ID
;
Future result = teams.delete(
teamId: '[TEAM_ID]',
);
result
.then((response) {
print(response);
}).catchError((error) {
print(error);
});
@@ -0,0 +1,20 @@
import 'package:appwrite/appwrite.dart';
// Init SDK
Client client = Client();
Teams teams = Teams(client);
client
.setProject('5df5acd0d48c2') // Your project ID
;
Future result = teams.getMemberships(
teamId: '[TEAM_ID]',
);
result
.then((response) {
print(response);
}).catchError((error) {
print(error);
});
@@ -0,0 +1,20 @@
import 'package:appwrite/appwrite.dart';
// Init SDK
Client client = Client();
Teams teams = Teams(client);
client
.setProject('5df5acd0d48c2') // Your project ID
;
Future result = teams.get(
teamId: '[TEAM_ID]',
);
result
.then((response) {
print(response);
}).catchError((error) {
print(error);
});
@@ -0,0 +1,19 @@
import 'package:appwrite/appwrite.dart';
// Init SDK
Client client = Client();
Teams teams = Teams(client);
client
.setProject('5df5acd0d48c2') // Your project ID
;
Future result = teams.list(
);
result
.then((response) {
print(response);
}).catchError((error) {
print(error);
});
@@ -0,0 +1,23 @@
import 'package:appwrite/appwrite.dart';
// Init SDK
Client client = Client();
Teams teams = Teams(client);
client
.setProject('5df5acd0d48c2') // Your project ID
;
Future result = teams.updateMembershipStatus(
teamId: '[TEAM_ID]',
inviteId: '[INVITE_ID]',
userId: '[USER_ID]',
secret: '[SECRET]',
);
result
.then((response) {
print(response);
}).catchError((error) {
print(error);
});
@@ -0,0 +1,21 @@
import 'package:appwrite/appwrite.dart';
// Init SDK
Client client = Client();
Teams teams = Teams(client);
client
.setProject('5df5acd0d48c2') // Your project ID
;
Future result = teams.update(
teamId: '[TEAM_ID]',
name: '[NAME]',
);
result
.then((response) {
print(response);
}).catchError((error) {
print(error);
});
+55
View File
@@ -0,0 +1,55 @@
# Examples
Init your Appwrite client:
```dart
Client client = Client();
client
.setEndpoint('https://localhost/v1') // Your Appwrite Endpoint
.setProject('5e8cf4f46b5e8') // Your project ID
.setSelfSigned() // Remove in production
;
```
Create a new user and session:
```dart
Account account = Account(client);
Response user = await account.create(email: 'me@appwrite.io', password: 'password', name: 'My Name');
Response session = await account.createSession(email: 'me@appwrite.io', password: 'password');
```
Fetch user profile:
```dart
Account account = Account(client);
Response profile = await account.get();
```
Upload File:
```dart
Storage storage = Storage(client);
MultipartFile file = MultipartFile.fromFile('./path-to-file/image.jpg', filename: 'image.jpg');
storage.createFile(
file: file,
read: ['*'],
write: []
)
.then((response) {
print(response); // File uploaded!
})
.catchError((error) {
print(error.response);
});
```
All examples and API features are available at the [official Appwrite docs](https://appwrite.io/docs)
+4 -3
View File
@@ -1,9 +1,10 @@
export 'package:dio/dio.dart' show Response;
export 'client.dart';
export 'enums.dart';
export 'services/account.dart';
export 'services/avatars.dart';
export 'services/database.dart';
export 'services/locale.dart';
export 'services/storage.dart';
export 'services/teams.dart';
export 'client.dart';
export 'enums.dart';
export 'package:dio/dio.dart' show Response;
+59 -10
View File
@@ -1,48 +1,77 @@
import 'dart:io';
import 'package:dio/adapter.dart';
import 'package:dio/dio.dart';
import 'package:dio/adapter.dart';
import 'package:dio_cookie_manager/dio_cookie_manager.dart';
import 'package:cookie_jar/cookie_jar.dart';
import 'package:path_provider/path_provider.dart';
import 'package:package_info/package_info.dart';
import 'enums.dart';
class Client {
String endPoint;
String type = 'unknown';
Map<String, String> headers;
Map<String, String> config;
bool selfSigned;
final Dio http;
bool init = false;
Dio http;
PersistCookieJar cookieJar;
Client({this.endPoint: 'https://appwrite.io/v1', this.selfSigned: false, Dio http}) : this.http = http ?? Dio() {
Client({this.endPoint = 'https://appwrite.io/v1', this.selfSigned = false, Dio http}) : this.http = http ?? Dio() {
type = (Platform.isIOS) ? 'ios' : type;
type = (Platform.isMacOS) ? 'macos' : type;
type = (Platform.isAndroid) ? 'android' : type;
type = (Platform.isLinux) ? 'linux' : type;
type = (Platform.isWindows) ? 'windows' : type;
type = (Platform.isFuchsia) ? 'fuchsia' : type;
this.headers = {
'content-type': 'application/json',
'x-sdk-version': 'appwrite:dart:0.0.8',
'x-sdk-version': 'appwrite:dart:0.1.1',
};
this.config = {};
assert(endPoint.startsWith(RegExp("http://|https://")), "endPoint $endPoint must start with 'http'");
this.http.options.baseUrl = this.endPoint;
this.http.options.validateStatus = (status) => status != 404;
this.http.interceptors.add(CookieManager(CookieJar()));
}
Future<Directory> _getCookiePath() async {
final directory = await getApplicationDocumentsDirectory();
final path = directory.path;
final Directory dir = new Directory('$path/cookies');
await dir.create();
return dir;
}
/// Your project ID
Client setProject(value) {
config['project'] = value;
addHeader('X-Appwrite-Project', value);
return this;
}
/// Your secret API key
Client setKey(value) {
config['key'] = value;
addHeader('X-Appwrite-Key', value);
return this;
}
Client setLocale(value) {
config['locale'] = value;
addHeader('X-Appwrite-Locale', value);
return this;
}
Client setMode(value) {
config['mode'] = value;
addHeader('X-Appwrite-Mode', value);
return this;
}
Client setSelfSigned({bool status = true}) {
selfSigned = status;
return this;
@@ -60,8 +89,8 @@ class Client {
return this;
}
Future<Response> call(HttpMethod method, {String path = '', Map<String, String> headers = const {}, Map<String, dynamic> params = const {}}) {
if(this.selfSigned) {
Future<Response> call(HttpMethod method, {String path = '', Map<String, String> headers = const {}, Map<String, dynamic> params = const {}}) async {
if(selfSigned) {
// Allow self signed requests
(http.httpClientAdapter as DefaultHttpClientAdapter).onHttpClientCreate = (HttpClient client) {
client.badCertificateCallback = (X509Certificate cert, String host, int port) => true;
@@ -69,12 +98,32 @@ class Client {
};
}
if(!init) {
final Directory cookieDir = await _getCookiePath();
cookieJar = new PersistCookieJar(dir:cookieDir.path);
this.http.options.baseUrl = this.endPoint;
this.http.options.validateStatus = (status) => status < 400;
this.http.interceptors.add(CookieManager(cookieJar));
PackageInfo packageInfo = await PackageInfo.fromPlatform();
addHeader('Origin', 'appwrite-' + type + '://' + packageInfo.packageName);
init = true;
}
// Origin is hardcoded for testing
Options options = Options(
headers: {...this.headers, ...headers, "Origin": "http://localhost"},
headers: {...this.headers, ...headers},
method: method.name(),
);
if(headers['content-type'] == 'multipart/form-data') {
return http.request(path, data: FormData.fromMap(params), options: options);
}
if (method == HttpMethod.get) {
return http.get(path, queryParameters: params, options: options);
} else {
+8 -12
View File
@@ -1,19 +1,15 @@
enum HttpMethod {
get, post, put, delete, patch
}
enum HttpMethod { get, post, put, delete, patch }
extension HttpMethodString on HttpMethod {
String name(){
return this.toString().split('.').last.toUpperCase();
}
String name() {
return this.toString().split('.').last.toUpperCase();
}
}
enum OrderType {
asc, desc
}
enum OrderType { asc, desc }
extension OrderTypeString on OrderType {
String name(){
return this.toString().split('.').last.toUpperCase();
}
String name() {
return this.toString().split('.').last.toUpperCase();
}
}
+3 -3
View File
@@ -1,7 +1,7 @@
import 'client.dart';
class Service {
final Client client;
final Client client;
const Service(this.client);
}
const Service(this.client);
}
+178 -21
View File
@@ -1,31 +1,44 @@
import 'dart:io';
import 'package:dio/dio.dart';
import 'package:meta/meta.dart';
import 'package:flutter_web_auth/flutter_web_auth.dart';
import "../client.dart";
import '../enums.dart';
import "../service.dart";
class Account extends Service {
Account(Client client): super(client);
/// Get Account
///
/// Get currently logged in user data as JSON object.
///
Future<Response> get() {
final String path = '/account';
final Map<String, dynamic> params = {
};
return this.client.call(HttpMethod.get, path: path, params: params);
final Map<String, String> headers = {
'content-type': 'application/json',
};
return client.call(HttpMethod.get, path: path, params: params, headers: headers);
}
/// Create Account
///
/// Use this endpoint to allow a new user to register a new account in your
/// project. After the user registration completes successfully, you can use
/// the [/account/verfication](/docs/account#createVerification) route to start
/// verifying the user email address. To allow your new user to login to his
/// new account, you need to create a new [account
/// session](/docs/account#createSession).
Future<Response> create({@required String email, @required String password, String name = null}) {
///
Future<Response> create({@required String email, @required String password, String name = ''}) {
final String path = '/account';
final Map<String, dynamic> params = {
@@ -34,25 +47,41 @@ class Account extends Service {
'name': name,
};
return this.client.call(HttpMethod.post, path: path, params: params);
final Map<String, String> headers = {
'content-type': 'application/json',
};
return client.call(HttpMethod.post, path: path, params: params, headers: headers);
}
/// Delete Account
///
/// Delete a currently logged in user account. Behind the scene, the user
/// record is not deleted but permanently blocked from any access. This is done
/// to avoid deleted accounts being overtaken by new users with the same email
/// address. Any user-related resources like documents or storage files should
/// be deleted separately.
///
Future<Response> delete() {
final String path = '/account';
final Map<String, dynamic> params = {
};
return this.client.call(HttpMethod.delete, path: path, params: params);
final Map<String, String> headers = {
'content-type': 'application/json',
};
return client.call(HttpMethod.delete, path: path, params: params, headers: headers);
}
/// Update Account Email
///
/// Update currently logged in user account email address. After changing user
/// address, user confirmation status is being reset and a new confirmation
/// mail is sent. For security measures, user password is required to complete
/// this request.
///
Future<Response> updateEmail({@required String email, @required String password}) {
final String path = '/account/email';
@@ -61,19 +90,35 @@ class Account extends Service {
'password': password,
};
return this.client.call(HttpMethod.patch, path: path, params: params);
final Map<String, String> headers = {
'content-type': 'application/json',
};
return client.call(HttpMethod.patch, path: path, params: params, headers: headers);
}
/// Get Account Logs
///
/// Get currently logged in user list of latest security activity logs. Each
/// log returns user IP address, location and date and time of log.
///
Future<Response> getLogs() {
final String path = '/account/logs';
final Map<String, dynamic> params = {
};
return this.client.call(HttpMethod.get, path: path, params: params);
final Map<String, String> headers = {
'content-type': 'application/json',
};
return client.call(HttpMethod.get, path: path, params: params, headers: headers);
}
/// Update Account Name
///
/// Update currently logged in user account name.
///
Future<Response> updateName({@required String name}) {
final String path = '/account/name';
@@ -81,10 +126,18 @@ class Account extends Service {
'name': name,
};
return this.client.call(HttpMethod.patch, path: path, params: params);
final Map<String, String> headers = {
'content-type': 'application/json',
};
return client.call(HttpMethod.patch, path: path, params: params, headers: headers);
}
/// Update Account Password
///
/// Update currently logged in user password. For validation, user is required
/// to pass the password twice.
///
Future<Response> updatePassword({@required String password, @required String oldPassword}) {
final String path = '/account/password';
@@ -93,19 +146,35 @@ class Account extends Service {
'old-password': oldPassword,
};
return this.client.call(HttpMethod.patch, path: path, params: params);
final Map<String, String> headers = {
'content-type': 'application/json',
};
return client.call(HttpMethod.patch, path: path, params: params, headers: headers);
}
/// Get Account Preferences
///
/// Get currently logged in user preferences as a key-value object.
///
Future<Response> getPrefs() {
final String path = '/account/prefs';
final Map<String, dynamic> params = {
};
return this.client.call(HttpMethod.get, path: path, params: params);
final Map<String, String> headers = {
'content-type': 'application/json',
};
return client.call(HttpMethod.get, path: path, params: params, headers: headers);
}
/// Update Account Preferences
///
/// Update currently logged in user account preferences. You can pass only the
/// specific settings you wish to update.
///
Future<Response> updatePrefs({@required dynamic prefs}) {
final String path = '/account/prefs';
@@ -113,14 +182,22 @@ class Account extends Service {
'prefs': prefs,
};
return this.client.call(HttpMethod.patch, path: path, params: params);
final Map<String, String> headers = {
'content-type': 'application/json',
};
return client.call(HttpMethod.patch, path: path, params: params, headers: headers);
}
/// Create Password Recovery
///
/// Sends the user an email with a temporary secret key for password reset.
/// When the user clicks the confirmation link he is redirected back to your
/// app password reset URL with the secret key and email address values
/// attached to the URL query string. Use the query string params to submit a
/// request to the [PUT /account/recovery](/docs/account#updateRecovery)
/// endpoint to complete the process.
///
Future<Response> createRecovery({@required String email, @required String url}) {
final String path = '/account/recovery';
@@ -129,8 +206,15 @@ class Account extends Service {
'url': url,
};
return this.client.call(HttpMethod.post, path: path, params: params);
final Map<String, String> headers = {
'content-type': 'application/json',
};
return client.call(HttpMethod.post, path: path, params: params, headers: headers);
}
/// Complete Password Recovery
///
/// Use this endpoint to complete the user account password reset. Both the
/// **userId** and **secret** arguments will be passed as query parameters to
/// the redirect URL you have provided when sending your request to the [POST
@@ -140,6 +224,7 @@ class Account extends Service {
/// Attack](https://github.com/OWASP/CheatSheetSeries/blob/master/cheatsheets/Unvalidated_Redirects_and_Forwards_Cheat_Sheet.md)
/// the only valid redirect URLs are the ones from domains you have set when
/// adding your platforms in the console interface.
///
Future<Response> updateRecovery({@required String userId, @required String secret, @required String passwordA, @required String passwordB}) {
final String path = '/account/recovery';
@@ -150,20 +235,36 @@ class Account extends Service {
'password-b': passwordB,
};
return this.client.call(HttpMethod.put, path: path, params: params);
final Map<String, String> headers = {
'content-type': 'application/json',
};
return client.call(HttpMethod.put, path: path, params: params, headers: headers);
}
/// Get Account Sessions
///
/// Get currently logged in user list of active sessions across different
/// devices.
///
Future<Response> getSessions() {
final String path = '/account/sessions';
final Map<String, dynamic> params = {
};
return this.client.call(HttpMethod.get, path: path, params: params);
final Map<String, String> headers = {
'content-type': 'application/json',
};
return client.call(HttpMethod.get, path: path, params: params, headers: headers);
}
/// Create Account Session
///
/// Allow the user to login into his account by providing a valid email and
/// password combination. This route will create a new session for the user.
///
Future<Response> createSession({@required String email, @required String password}) {
final String path = '/account/sessions';
@@ -172,43 +273,86 @@ class Account extends Service {
'password': password,
};
return this.client.call(HttpMethod.post, path: path, params: params);
final Map<String, String> headers = {
'content-type': 'application/json',
};
return client.call(HttpMethod.post, path: path, params: params, headers: headers);
}
/// Delete All Account Sessions
///
/// Delete all sessions from the user account and remove any sessions cookies
/// from the end client.
///
Future<Response> deleteSessions() {
final String path = '/account/sessions';
final Map<String, dynamic> params = {
};
return this.client.call(HttpMethod.delete, path: path, params: params);
final Map<String, String> headers = {
'content-type': 'application/json',
};
return client.call(HttpMethod.delete, path: path, params: params, headers: headers);
}
/// Create Account Session with OAuth2
///
/// Allow the user to login to his account using the OAuth2 provider of his
/// choice. Each OAuth2 provider should be enabled from the Appwrite console
/// first. Use the success and failure arguments to provide a redirect URL's
/// back to your app when login is completed.
Future<Response> createOAuth2Session({@required String provider, @required String success, @required String failure}) {
///
Future createOAuth2Session({@required String provider, String success = 'https://localhost:2444/auth/oauth2/success', String failure = 'https://localhost:2444/auth/oauth2/failure'}) {
final String path = '/account/sessions/oauth2/{provider}'.replaceAll(RegExp('{provider}'), provider);
final Map<String, dynamic> params = {
'success': success,
'failure': failure,
'project': client.config['project'],
};
return this.client.call(HttpMethod.get, path: path, params: params);
Uri endpoint = Uri.parse(client.endPoint);
Uri url = new Uri(scheme: endpoint.scheme,
host: endpoint.host,
port: endpoint.port,
path: endpoint.path + path,
queryParameters:params,
);
return FlutterWebAuth.authenticate(
url: url.toString(),
callbackUrlScheme: "appwrite-callback"
).then((value) {
Uri url = Uri.parse(value);
List<Cookie> cookies = [new Cookie(url.queryParameters['key'], url.queryParameters['secret'])];
client.cookieJar.saveFromResponse(Uri.parse(client.endPoint), cookies);
});
}
/// Delete Account Session
///
/// Use this endpoint to log out the currently logged in user from all his
/// account sessions across all his different devices. When using the option id
/// argument, only the session unique ID provider will be deleted.
///
Future<Response> deleteSession({@required String sessionId}) {
final String path = '/account/sessions/{sessionId}'.replaceAll(RegExp('{sessionId}'), sessionId);
final Map<String, dynamic> params = {
};
return this.client.call(HttpMethod.delete, path: path, params: params);
final Map<String, String> headers = {
'content-type': 'application/json',
};
return client.call(HttpMethod.delete, path: path, params: params, headers: headers);
}
/// Create Email Verification
///
/// Use this endpoint to send a verification message to your user email address
/// to confirm they are the valid owners of that address. Both the **userId**
/// and **secret** arguments will be passed as query parameters to the URL you
@@ -222,6 +366,7 @@ class Account extends Service {
/// Attack](https://github.com/OWASP/CheatSheetSeries/blob/master/cheatsheets/Unvalidated_Redirects_and_Forwards_Cheat_Sheet.md)
/// the only valid redirect URLs are the ones from domains you have set when
/// adding your platforms in the console interface.
///
Future<Response> createVerification({@required String url}) {
final String path = '/account/verification';
@@ -229,12 +374,20 @@ class Account extends Service {
'url': url,
};
return this.client.call(HttpMethod.post, path: path, params: params);
final Map<String, String> headers = {
'content-type': 'application/json',
};
return client.call(HttpMethod.post, path: path, params: params, headers: headers);
}
/// Complete Email Verification
///
/// Use this endpoint to complete the user email verification process. Use both
/// the **userId** and **secret** parameters that were attached to your app URL
/// to verify the user email ownership. If confirmed this route will return a
/// 200 status code.
///
Future<Response> updateVerification({@required String userId, @required String secret}) {
final String path = '/account/verification';
@@ -243,6 +396,10 @@ class Account extends Service {
'secret': secret,
};
return this.client.call(HttpMethod.put, path: path, params: params);
final Map<String, String> headers = {
'content-type': 'application/json',
};
return client.call(HttpMethod.put, path: path, params: params, headers: headers);
}
}
@@ -1,4 +1,5 @@
import 'package:dio/dio.dart';
import 'package:meta/meta.dart';
@@ -7,13 +8,15 @@ import '../enums.dart';
import "../service.dart";
class Avatars extends Service {
Avatars(Client client): super(client);
/// Get Browser Icon
///
/// You can use this endpoint to show different browser icons to your users.
/// The code argument receives the browser code as it appears in your user
/// /account/sessions endpoint. Use width, height and quality arguments to
/// change the output settings.
///
Future<Response> getBrowser({@required String code, int width = 100, int height = 100, int quality = 100}) {
final String path = '/avatars/browsers/{code}'.replaceAll(RegExp('{code}'), code);
@@ -23,12 +26,20 @@ class Avatars extends Service {
'quality': quality,
};
return this.client.call(HttpMethod.get, path: path, params: params);
final Map<String, String> headers = {
'content-type': 'application/json',
};
return client.call(HttpMethod.get, path: path, params: params, headers: headers);
}
/// Get Credit Card Icon
///
/// Need to display your users with your billing method or their payment
/// methods? The credit card endpoint will return you the icon of the credit
/// card provider you need. Use width, height and quality arguments to change
/// the output settings.
///
Future<Response> getCreditCard({@required String code, int width = 100, int height = 100, int quality = 100}) {
final String path = '/avatars/credit-cards/{code}'.replaceAll(RegExp('{code}'), code);
@@ -38,10 +49,18 @@ class Avatars extends Service {
'quality': quality,
};
return this.client.call(HttpMethod.get, path: path, params: params);
final Map<String, String> headers = {
'content-type': 'application/json',
};
return client.call(HttpMethod.get, path: path, params: params, headers: headers);
}
/// Get Favicon
///
/// Use this endpoint to fetch the favorite icon (AKA favicon) of a any remote
/// website URL.
///
Future<Response> getFavicon({@required String url}) {
final String path = '/avatars/favicon';
@@ -49,11 +68,19 @@ class Avatars extends Service {
'url': url,
};
return this.client.call(HttpMethod.get, path: path, params: params);
final Map<String, String> headers = {
'content-type': 'application/json',
};
return client.call(HttpMethod.get, path: path, params: params, headers: headers);
}
/// Get Country Flag
///
/// You can use this endpoint to show different country flags icons to your
/// users. The code argument receives the 2 letter country code. Use width,
/// height and quality arguments to change the output settings.
///
Future<Response> getFlag({@required String code, int width = 100, int height = 100, int quality = 100}) {
final String path = '/avatars/flags/{code}'.replaceAll(RegExp('{code}'), code);
@@ -63,12 +90,20 @@ class Avatars extends Service {
'quality': quality,
};
return this.client.call(HttpMethod.get, path: path, params: params);
final Map<String, String> headers = {
'content-type': 'application/json',
};
return client.call(HttpMethod.get, path: path, params: params, headers: headers);
}
/// Get Image from URL
///
/// Use this endpoint to fetch a remote image URL and crop it to any image size
/// you want. This endpoint is very useful if you need to crop and display
/// remote images in your app or in case you want to make sure a 3rd party
/// image is properly served using a TLS protocol.
///
Future<Response> getImage({@required String url, int width = 400, int height = 400}) {
final String path = '/avatars/image';
@@ -78,11 +113,19 @@ class Avatars extends Service {
'height': height,
};
return this.client.call(HttpMethod.get, path: path, params: params);
final Map<String, String> headers = {
'content-type': 'application/json',
};
return client.call(HttpMethod.get, path: path, params: params, headers: headers);
}
/// Get QR Code
///
/// Converts a given plain text to a QR code image. You can use the query
/// parameters to change the size and style of the resulting image.
Future<Response> getQR({@required String text, int size = 400, int margin = 1, int download = null}) {
///
Future<Response> getQR({@required String text, int size = 400, int margin = 1, int download = 0}) {
final String path = '/avatars/qr';
final Map<String, dynamic> params = {
@@ -92,6 +135,10 @@ class Avatars extends Service {
'download': download,
};
return this.client.call(HttpMethod.get, path: path, params: params);
final Map<String, String> headers = {
'content-type': 'application/json',
};
return client.call(HttpMethod.get, path: path, params: params, headers: headers);
}
}
@@ -1,4 +1,5 @@
import 'package:dio/dio.dart';
import 'package:meta/meta.dart';
@@ -7,14 +8,16 @@ import '../enums.dart';
import "../service.dart";
class Database extends Service {
Database(Client client): super(client);
/// List Documents
///
/// Get a list of all the user documents. You can use the query params to
/// filter your results. On admin mode, this endpoint will return a list of all
/// of the project documents. [Learn more about different API
/// modes](/docs/admin).
Future<Response> listDocuments({@required String collectionId, List filters = const [], int offset = null, int limit = 50, String orderField = '\$id', String orderType = 'ASC', String orderCast = 'string', String search = null, int first = null, int last = null}) {
///
Future<Response> listDocuments({@required String collectionId, List filters = const [], int offset = 0, int limit = 50, String orderField = '\$id', String orderType = 'ASC', String orderCast = 'string', String search = '', int first = 0, int last = 0}) {
final String path = '/database/collections/{collectionId}/documents'.replaceAll(RegExp('{collectionId}'), collectionId);
final Map<String, dynamic> params = {
@@ -29,10 +32,18 @@ class Database extends Service {
'last': last,
};
return this.client.call(HttpMethod.get, path: path, params: params);
final Map<String, String> headers = {
'content-type': 'application/json',
};
return client.call(HttpMethod.get, path: path, params: params, headers: headers);
}
/// Create Document
///
/// Create a new Document.
Future<Response> createDocument({@required String collectionId, @required dynamic data, @required List read, @required List write, String parentDocument = null, String parentProperty = null, String parentPropertyType = 'assign'}) {
///
Future<Response> createDocument({@required String collectionId, @required dynamic data, @required List read, @required List write, String parentDocument = '', String parentProperty = '', String parentPropertyType = 'assign'}) {
final String path = '/database/collections/{collectionId}/documents'.replaceAll(RegExp('{collectionId}'), collectionId);
final Map<String, dynamic> params = {
@@ -44,18 +55,32 @@ class Database extends Service {
'parentPropertyType': parentPropertyType,
};
return this.client.call(HttpMethod.post, path: path, params: params);
final Map<String, String> headers = {
'content-type': 'application/json',
};
return client.call(HttpMethod.post, path: path, params: params, headers: headers);
}
/// Get Document
///
/// Get document by its unique ID. This endpoint response returns a JSON object
/// with the document data.
///
Future<Response> getDocument({@required String collectionId, @required String documentId}) {
final String path = '/database/collections/{collectionId}/documents/{documentId}'.replaceAll(RegExp('{collectionId}'), collectionId).replaceAll(RegExp('{documentId}'), documentId);
final Map<String, dynamic> params = {
};
return this.client.call(HttpMethod.get, path: path, params: params);
final Map<String, String> headers = {
'content-type': 'application/json',
};
return client.call(HttpMethod.get, path: path, params: params, headers: headers);
}
/// Update Document
Future<Response> updateDocument({@required String collectionId, @required String documentId, @required dynamic data, @required List read, @required List write}) {
final String path = '/database/collections/{collectionId}/documents/{documentId}'.replaceAll(RegExp('{collectionId}'), collectionId).replaceAll(RegExp('{documentId}'), documentId);
@@ -65,17 +90,29 @@ class Database extends Service {
'write': write,
};
return this.client.call(HttpMethod.patch, path: path, params: params);
final Map<String, String> headers = {
'content-type': 'application/json',
};
return client.call(HttpMethod.patch, path: path, params: params, headers: headers);
}
/// Delete Document
///
/// Delete document by its unique ID. This endpoint deletes only the parent
/// documents, his attributes and relations to other documents. Child documents
/// **will not** be deleted.
///
Future<Response> deleteDocument({@required String collectionId, @required String documentId}) {
final String path = '/database/collections/{collectionId}/documents/{documentId}'.replaceAll(RegExp('{collectionId}'), collectionId).replaceAll(RegExp('{documentId}'), documentId);
final Map<String, dynamic> params = {
};
return this.client.call(HttpMethod.delete, path: path, params: params);
final Map<String, String> headers = {
'content-type': 'application/json',
};
return client.call(HttpMethod.delete, path: path, params: params, headers: headers);
}
}
+54 -7
View File
@@ -1,4 +1,5 @@
import 'package:dio/dio.dart';
import 'package:meta/meta.dart';
@@ -7,72 +8,118 @@ import '../enums.dart';
import "../service.dart";
class Locale extends Service {
Locale(Client client): super(client);
/// Get User Locale
///
/// Get the current user location based on IP. Returns an object with user
/// country code, country name, continent name, continent code, ip address and
/// suggested currency. You can use the locale header to get the data in a
/// supported language.
///
/// ([IP Geolocation by DB-IP](https://db-ip.com))
///
Future<Response> get() {
final String path = '/locale';
final Map<String, dynamic> params = {
};
return this.client.call(HttpMethod.get, path: path, params: params);
final Map<String, String> headers = {
'content-type': 'application/json',
};
return client.call(HttpMethod.get, path: path, params: params, headers: headers);
}
/// List Continents
///
/// List of all continents. You can use the locale header to get the data in a
/// supported language.
///
Future<Response> getContinents() {
final String path = '/locale/continents';
final Map<String, dynamic> params = {
};
return this.client.call(HttpMethod.get, path: path, params: params);
final Map<String, String> headers = {
'content-type': 'application/json',
};
return client.call(HttpMethod.get, path: path, params: params, headers: headers);
}
/// List Countries
///
/// List of all countries. You can use the locale header to get the data in a
/// supported language.
///
Future<Response> getCountries() {
final String path = '/locale/countries';
final Map<String, dynamic> params = {
};
return this.client.call(HttpMethod.get, path: path, params: params);
final Map<String, String> headers = {
'content-type': 'application/json',
};
return client.call(HttpMethod.get, path: path, params: params, headers: headers);
}
/// List EU Countries
///
/// List of all countries that are currently members of the EU. You can use the
/// locale header to get the data in a supported language.
///
Future<Response> getCountriesEU() {
final String path = '/locale/countries/eu';
final Map<String, dynamic> params = {
};
return this.client.call(HttpMethod.get, path: path, params: params);
final Map<String, String> headers = {
'content-type': 'application/json',
};
return client.call(HttpMethod.get, path: path, params: params, headers: headers);
}
/// List Countries Phone Codes
///
/// List of all countries phone codes. You can use the locale header to get the
/// data in a supported language.
///
Future<Response> getCountriesPhones() {
final String path = '/locale/countries/phones';
final Map<String, dynamic> params = {
};
return this.client.call(HttpMethod.get, path: path, params: params);
final Map<String, String> headers = {
'content-type': 'application/json',
};
return client.call(HttpMethod.get, path: path, params: params, headers: headers);
}
/// List Currencies
///
/// List of all currencies, including currency symol, name, plural, and decimal
/// digits for all major and minor currencies. You can use the locale header to
/// get the data in a supported language.
///
Future<Response> getCurrencies() {
final String path = '/locale/currencies';
final Map<String, dynamic> params = {
};
return this.client.call(HttpMethod.get, path: path, params: params);
final Map<String, String> headers = {
'content-type': 'application/json',
};
return client.call(HttpMethod.get, path: path, params: params, headers: headers);
}
}
+92 -14
View File
@@ -1,4 +1,5 @@
import 'package:dio/dio.dart';
import 'package:meta/meta.dart';
@@ -7,13 +8,15 @@ import '../enums.dart';
import "../service.dart";
class Storage extends Service {
Storage(Client client): super(client);
/// List Files
///
/// Get a list of all the user files. You can use the query params to filter
/// your results. On admin mode, this endpoint will return a list of all of the
/// project files. [Learn more about different API modes](/docs/admin).
Future<Response> listFiles({String search = null, int limit = 25, int offset = null, OrderType orderType = OrderType.asc}) {
///
Future<Response> listFiles({String search = '', int limit = 25, int offset = 0, OrderType orderType = OrderType.asc}) {
final String path = '/storage/files';
final Map<String, dynamic> params = {
@@ -23,12 +26,20 @@ class Storage extends Service {
'orderType': orderType.name(),
};
return this.client.call(HttpMethod.get, path: path, params: params);
final Map<String, String> headers = {
'content-type': 'application/json',
};
return client.call(HttpMethod.get, path: path, params: params, headers: headers);
}
/// Create File
///
/// Create a new file. The user who creates the file will automatically be
/// assigned to read and write access unless he has passed custom values for
/// read and write arguments.
Future<Response> createFile({@required file, @required List read, @required List write}) {
///
Future<Response> createFile({@required MultipartFile file, @required List read, @required List write}) {
final String path = '/storage/files';
final Map<String, dynamic> params = {
@@ -37,20 +48,36 @@ class Storage extends Service {
'write': write,
};
return this.client.call(HttpMethod.post, path: path, params: params);
final Map<String, String> headers = {
'content-type': 'multipart/form-data',
};
return client.call(HttpMethod.post, path: path, params: params, headers: headers);
}
/// Get File
///
/// Get file by its unique ID. This endpoint response returns a JSON object
/// with the file metadata.
///
Future<Response> getFile({@required String fileId}) {
final String path = '/storage/files/{fileId}'.replaceAll(RegExp('{fileId}'), fileId);
final Map<String, dynamic> params = {
};
return this.client.call(HttpMethod.get, path: path, params: params);
final Map<String, String> headers = {
'content-type': 'application/json',
};
return client.call(HttpMethod.get, path: path, params: params, headers: headers);
}
/// Update File
///
/// Update file by its unique ID. Only users with write permissions have access
/// to update this resource.
///
Future<Response> updateFile({@required String fileId, @required List read, @required List write}) {
final String path = '/storage/files/{fileId}'.replaceAll(RegExp('{fileId}'), fileId);
@@ -59,34 +86,63 @@ class Storage extends Service {
'write': write,
};
return this.client.call(HttpMethod.put, path: path, params: params);
final Map<String, String> headers = {
'content-type': 'application/json',
};
return client.call(HttpMethod.put, path: path, params: params, headers: headers);
}
/// Delete File
///
/// Delete a file by its unique ID. Only users with write permissions have
/// access to delete this resource.
///
Future<Response> deleteFile({@required String fileId}) {
final String path = '/storage/files/{fileId}'.replaceAll(RegExp('{fileId}'), fileId);
final Map<String, dynamic> params = {
};
return this.client.call(HttpMethod.delete, path: path, params: params);
final Map<String, String> headers = {
'content-type': 'application/json',
};
return client.call(HttpMethod.delete, path: path, params: params, headers: headers);
}
/// Get File for Download
///
/// Get file content by its unique ID. The endpoint response return with a
/// 'Content-Disposition: attachment' header that tells the browser to start
/// downloading the file to user downloads directory.
Future<Response> getFileDownload({@required String fileId}) {
///
String getFileDownload({@required String fileId}) {
final String path = '/storage/files/{fileId}/download'.replaceAll(RegExp('{fileId}'), fileId);
final Map<String, dynamic> params = {
'project': client.config['project'],
};
return this.client.call(HttpMethod.get, path: path, params: params);
Uri endpoint = Uri.parse(client.endPoint);
Uri url = new Uri(scheme: endpoint.scheme,
host: endpoint.host,
port: endpoint.port,
path: endpoint.path + path,
queryParameters:params,
);
return url.toString();
}
/// Get File Preview
///
/// Get a file preview image. Currently, this method supports preview for image
/// files (jpg, png, and gif), other supported formats, like pdf, docs, slides,
/// and spreadsheets, will return the file icon image. You can also pass query
/// string arguments for cutting and resizing your preview image.
Future<Response> getFilePreview({@required String fileId, int width = null, int height = null, int quality = 100, String background = null, String output = null}) {
///
String getFilePreview({@required String fileId, int width = 0, int height = 0, int quality = 100, String background = '', String output = ''}) {
final String path = '/storage/files/{fileId}/preview'.replaceAll(RegExp('{fileId}'), fileId);
final Map<String, dynamic> params = {
@@ -95,19 +151,41 @@ class Storage extends Service {
'quality': quality,
'background': background,
'output': output,
'project': client.config['project'],
};
return this.client.call(HttpMethod.get, path: path, params: params);
Uri endpoint = Uri.parse(client.endPoint);
Uri url = new Uri(scheme: endpoint.scheme,
host: endpoint.host,
port: endpoint.port,
path: endpoint.path + path,
queryParameters:params,
);
return url.toString();
}
/// Get File for View
///
/// Get file content by its unique ID. This endpoint is similar to the download
/// method but returns with no 'Content-Disposition: attachment' header.
Future<Response> getFileView({@required String fileId, String as = null}) {
///
String getFileView({@required String fileId, String as = ''}) {
final String path = '/storage/files/{fileId}/view'.replaceAll(RegExp('{fileId}'), fileId);
final Map<String, dynamic> params = {
'as': as,
'project': client.config['project'],
};
return this.client.call(HttpMethod.get, path: path, params: params);
Uri endpoint = Uri.parse(client.endPoint);
Uri url = new Uri(scheme: endpoint.scheme,
host: endpoint.host,
port: endpoint.port,
path: endpoint.path + path,
queryParameters:params,
);
return url.toString();
}
}
+83 -12
View File
@@ -1,4 +1,5 @@
import 'package:dio/dio.dart';
import 'package:meta/meta.dart';
@@ -7,13 +8,15 @@ import '../enums.dart';
import "../service.dart";
class Teams extends Service {
Teams(Client client): super(client);
/// List Teams
///
/// Get a list of all the current user teams. You can use the query params to
/// filter your results. On admin mode, this endpoint will return a list of all
/// of the project teams. [Learn more about different API modes](/docs/admin).
Future<Response> list({String search = null, int limit = 25, int offset = null, OrderType orderType = OrderType.asc}) {
///
Future<Response> list({String search = '', int limit = 25, int offset = 0, OrderType orderType = OrderType.asc}) {
final String path = '/teams';
final Map<String, dynamic> params = {
@@ -23,12 +26,20 @@ class Teams extends Service {
'orderType': orderType.name(),
};
return this.client.call(HttpMethod.get, path: path, params: params);
final Map<String, String> headers = {
'content-type': 'application/json',
};
return client.call(HttpMethod.get, path: path, params: params, headers: headers);
}
/// Create Team
///
/// Create a new team. The user who creates the team will automatically be
/// assigned as the owner of the team. The team owner can invite new members,
/// who will be able add new owners and update or delete the team from your
/// project.
///
Future<Response> create({@required String name, List roles = const ["owner"]}) {
final String path = '/teams';
@@ -37,20 +48,36 @@ class Teams extends Service {
'roles': roles,
};
return this.client.call(HttpMethod.post, path: path, params: params);
final Map<String, String> headers = {
'content-type': 'application/json',
};
return client.call(HttpMethod.post, path: path, params: params, headers: headers);
}
/// Get Team
///
/// Get team by its unique ID. All team members have read access for this
/// resource.
///
Future<Response> get({@required String teamId}) {
final String path = '/teams/{teamId}'.replaceAll(RegExp('{teamId}'), teamId);
final Map<String, dynamic> params = {
};
return this.client.call(HttpMethod.get, path: path, params: params);
final Map<String, String> headers = {
'content-type': 'application/json',
};
return client.call(HttpMethod.get, path: path, params: params, headers: headers);
}
/// Update Team
///
/// Update team by its unique ID. Only team owners have write access for this
/// resource.
///
Future<Response> update({@required String teamId, @required String name}) {
final String path = '/teams/{teamId}'.replaceAll(RegExp('{teamId}'), teamId);
@@ -58,28 +85,51 @@ class Teams extends Service {
'name': name,
};
return this.client.call(HttpMethod.put, path: path, params: params);
final Map<String, String> headers = {
'content-type': 'application/json',
};
return client.call(HttpMethod.put, path: path, params: params, headers: headers);
}
/// Delete Team
///
/// Delete team by its unique ID. Only team owners have write access for this
/// resource.
///
Future<Response> delete({@required String teamId}) {
final String path = '/teams/{teamId}'.replaceAll(RegExp('{teamId}'), teamId);
final Map<String, dynamic> params = {
};
return this.client.call(HttpMethod.delete, path: path, params: params);
final Map<String, String> headers = {
'content-type': 'application/json',
};
return client.call(HttpMethod.delete, path: path, params: params, headers: headers);
}
/// Get Team Memberships
///
/// Get team members by the team unique ID. All team members have read access
/// for this list of resources.
///
Future<Response> getMemberships({@required String teamId}) {
final String path = '/teams/{teamId}/memberships'.replaceAll(RegExp('{teamId}'), teamId);
final Map<String, dynamic> params = {
};
return this.client.call(HttpMethod.get, path: path, params: params);
final Map<String, String> headers = {
'content-type': 'application/json',
};
return client.call(HttpMethod.get, path: path, params: params, headers: headers);
}
/// Create Team Membership
///
/// Use this endpoint to invite a new member to join your team. An email with a
/// link to join the team will be sent to the new member email address if the
/// member doesn't exist in the project it will be created automatically.
@@ -93,7 +143,8 @@ class Teams extends Service {
/// Attacks](https://github.com/OWASP/CheatSheetSeries/blob/master/cheatsheets/Unvalidated_Redirects_and_Forwards_Cheat_Sheet.md)
/// the only valid redirect URL's are the once from domains you have set when
/// added your platforms in the console interface.
Future<Response> createMembership({@required String teamId, @required String email, @required List roles, @required String url, String name = null}) {
///
Future<Response> createMembership({@required String teamId, @required String email, @required List roles, @required String url, String name = ''}) {
final String path = '/teams/{teamId}/memberships'.replaceAll(RegExp('{teamId}'), teamId);
final Map<String, dynamic> params = {
@@ -103,22 +154,38 @@ class Teams extends Service {
'url': url,
};
return this.client.call(HttpMethod.post, path: path, params: params);
final Map<String, String> headers = {
'content-type': 'application/json',
};
return client.call(HttpMethod.post, path: path, params: params, headers: headers);
}
/// Delete Team Membership
///
/// This endpoint allows a user to leave a team or for a team owner to delete
/// the membership of any other team member. You can also use this endpoint to
/// delete a user membership even if he didn't accept it.
///
Future<Response> deleteMembership({@required String teamId, @required String inviteId}) {
final String path = '/teams/{teamId}/memberships/{inviteId}'.replaceAll(RegExp('{teamId}'), teamId).replaceAll(RegExp('{inviteId}'), inviteId);
final Map<String, dynamic> params = {
};
return this.client.call(HttpMethod.delete, path: path, params: params);
final Map<String, String> headers = {
'content-type': 'application/json',
};
return client.call(HttpMethod.delete, path: path, params: params, headers: headers);
}
/// Update Team Membership Status
///
/// Use this endpoint to allow a user to accept an invitation to join a team
/// after he is being redirected back to your app from the invitation email he
/// was sent.
///
Future<Response> updateMembershipStatus({@required String teamId, @required String inviteId, @required String userId, @required String secret}) {
final String path = '/teams/{teamId}/memberships/{inviteId}/status'.replaceAll(RegExp('{teamId}'), teamId).replaceAll(RegExp('{inviteId}'), inviteId);
@@ -127,6 +194,10 @@ class Teams extends Service {
'secret': secret,
};
return this.client.call(HttpMethod.patch, path: path, params: params);
final Map<String, String> headers = {
'content-type': 'application/json',
};
return client.call(HttpMethod.patch, path: path, params: params, headers: headers);
}
}
+30 -3
View File
@@ -1,11 +1,38 @@
name: appwrite
version: 0.0.8
description: Appwrite backend as a service cuts up to 70% of the time and costs required for building a modern application. We abstract and simplify common development tasks behind a REST APIs, to help you develop your app in a fast and secure way. For full API documentation and tutorials go to [https://appwrite.io/docs](https://appwrite.io/docs)
homepage: https://github.com/appwrite/sdk-for-dart
version: 0.1.1
description: Appwrite is an open-source self-hosted backend server that abstract and simplify complex and repetitive development tasks behind a very simple REST API
homepage: https://appwrite.io
repository: https://github.com/appwrite/sdk-for-dart
issue_tracker: https://github.com/appwrite/sdk-generator/issues
documentation: https://appwrite.io/support
environment:
sdk: '>=2.6.0 <3.0.0'
dependencies:
meta: ^1.1.8
path_provider: ^1.6.5
package_info: ^0.4.0+16
dio: ^3.0.0
cookie_jar: ^1.0.0
dio_cookie_manager: ^1.0.0
flutter_web_auth: ^0.2.0
flutter:
sdk: flutter
# The following adds the Cupertino Icons font to your application.
# Use with the CupertinoIcons class for iOS style icons.
cupertino_icons: ^0.1.2
dev_dependencies:
flutter_test:
sdk: flutter
# For information on the generic Dart part of this file, see the
# following page: https://dart.dev/tools/pub/pubspec
# The following section is specific to Flutter.
flutter:
# The following line ensures that the Material Icons font is
# included with your application, so that you can use the icons in
# the material Icons class.
uses-material-design: true
-1
View File
@@ -8,7 +8,6 @@
![Appwrite](https://appwrite.io/images/github.png)
## Installation
-1
View File
@@ -6,7 +6,6 @@
![Appwrite](https://appwrite.io/images/github.png)
## Installation
-1
View File
@@ -6,7 +6,6 @@
![Appwrite](https://appwrite.io/images/github.png)
## Installation
-1
View File
@@ -8,7 +8,6 @@
![Appwrite](https://appwrite.io/images/github.png)
## Installation
-1
View File
@@ -8,7 +8,6 @@
![Appwrite](https://appwrite.io/images/github.png)
## Installation
-1
View File
@@ -4,7 +4,6 @@
![Version](https://img.shields.io/badge/api%20version-0.5.3-blue.svg?v=1)
![Appwrite](https://appwrite.io/images/github.png)
## Installation
+8
View File
@@ -55,11 +55,14 @@ $cli
//$spec = getSSLPage('http://localhost/v1/open-api-2.json?extensions=1&platform='.$language['family']);
$spec = getSSLPage('https://appwrite.io/v1/open-api-2.json?extensions=1&platform='.$language['family']);
$spec = getSSLPage('https://localhost:2444/v1/open-api-2.json?extensions=1&platform='.$language['family']);
$result = realpath(__DIR__.'/..').'/sdks/'.$key.'-'.$language['key'];
$target = realpath(__DIR__.'/..').'/sdks/git/'.$language['key'].'/';
$readme = realpath(__DIR__ . '/../../docs/sdks/'.$language['key'].'/README.md');
$readme = ($readme) ? file_get_contents($readme) : '';
$examples = realpath(__DIR__ . '/../../docs/sdks/'.$language['key'].'/EXAMPLES.md');
$examples = ($examples) ? file_get_contents($examples) : '';
$changelog = realpath(__DIR__ . '/../../docs/sdks/'.$language['key'].'/CHANGELOG.md');
$changelog = ($changelog) ? file_get_contents($changelog) : '# Change Log';
$warning = ($language['beta']) ? '**This SDK is compatible with Appwrite server version ' . $version . '. For older versions, please check previous releases.**' : '';
@@ -135,6 +138,10 @@ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
$sdk = new SDK($config, new Swagger2($spec));
$sdk
->setDescription("Appwrite is an open-source backend as a service server that abstract and simplify complex and repetitive development tasks behind a very simple to use REST API. Appwrite aims to help you develop your apps faster and in a more secure way.
Use the {$language['name']} SDK to integrate your app with the Appwrite server to easily start interacting with all of Appwrite backend APIs and tools.
For full API documentation and tutorials go to [https://appwrite.io/docs](https://appwrite.io/docs)")
->setShortDescription('Appwrite is an open-source self-hosted backend server that abstract and simplify complex and repetitive development tasks behind a very simple REST API')
->setLicense($license)
->setLicenseContent($licenseContent)
->setVersion($language['version'])
@@ -151,6 +158,7 @@ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
->setWarning($warning)
->setReadme($readme)
->setChangelog($changelog)
->setExamples($examples)
;
try {
+3 -3
View File
@@ -253,7 +253,7 @@
</span>
<div class="margin-top-small">
<img data-ls-attrs="src={{env.API}}/avatars/flags/{{session.geo.isoCode}}?width=80&height=80&project={{env.PROJECT}}" class="avatar xs margin-end-small inline" />
<img data-ls-attrs="src={{env.API}}/avatars/flags/{{session.geo.isoCode}}?width=80&height=80&project={{env.PROJECT}}" class="avatar xxs margin-end-small inline" />
<small data-ls-bind="{{session.ip}}"></small> / <small data-ls-bind="{{session.geo.country}}"></small>
</div>
</li>
@@ -302,11 +302,11 @@
<td data-title="Date: "><span data-ls-bind="{{log.time|date-time}}"></span></td>
<td data-title="Event: "><span data-ls-bind="{{log.event}}"></span></td>
<td data-title="Client: ">
<img data-ls-attrs="src={{env.API}}/avatars/browsers/{{log.client.short_name|lowercase}}?width=80&height=80&project={{env.PROJECT}},title={{log.client.name}},alt={{log.client.name}}" class="avatar xs inline margin-end-small" />
<img data-ls-attrs="src={{env.API}}/avatars/browsers/{{log.client.short_name|lowercase}}?width=80&height=80&project={{env.PROJECT}},title={{log.client.name}},alt={{log.client.name}}" class="avatar xxs inline margin-end-small" />
<span data-ls-bind="{{log.client.name}} {{log.client.version}} on {{log.model}} {{log.OS.name}} {{log.OS.version}}"></span>
</td>
<td data-title="Location: ">
<img data-ls-attrs="src={{env.API}}/avatars/flags/{{log.geo.isoCode}}?width=80&height=80&project={{env.PROJECT}}" class="avatar xs inline margin-end-small" />
<img data-ls-attrs="src={{env.API}}/avatars/flags/{{log.geo.isoCode}}?width=80&height=80&project={{env.PROJECT}}" class="avatar xxs inline margin-end-small" />
<span data-ls-bind="{{log.geo.country}}"></span>
</td>
<td data-title="IP: "><span data-ls-bind="{{log.ip}}"></span></td>
+173 -16
View File
@@ -87,6 +87,11 @@ $graph = $this->getParam('graph', false);
<div class="box margin-bottom" data-ls-if="0 < {{console-project.platforms.length}} && undefined !== {{console-project.platforms}}">
<ul data-ls-loop="console-project.platforms" data-ls-as="platform" class="list">
<li class="clear">
<div class="pull-end desktops-only">
<button data-ls-ui-trigger="platform-delete-{{platform.$id}}" class="reverse danger margin-end-small">Delete</button>
<button data-ls-ui-trigger="platform-update-{{platform.$id}}">Update</button>
</div>
<div data-ui-modal data-button-hide="on" data-open-event="platform-update-{{platform.$id}}">
<button type="button" class="close pull-end" data-ui-modal-close=""><i class="icon-cancel"></i></button>
@@ -114,17 +119,22 @@ $graph = $this->getParam('graph', false);
<input type="hidden" name="platformId" data-ls-bind="{{platform.$id}}" />
</form>
<div class="pull-end desktops-only">
<button data-ls-ui-trigger="platform-delete-{{platform.$id}}" class="reverse danger margin-end-small">Delete</button>
<button data-ls-ui-trigger="platform-update-{{platform.$id}}">Update</button>
<div>
<div class="pull-start margin-end avatar-container">
<img src="" data-ls-attrs="src=/images/clients/{{platform.type}}.png?v=<?php echo APP_CACHE_BUSTER; ?>" class="avatar" loading="lazy" width="60" height="60" />
<div data-ls-if="{{platform.type}} === 'flutter-ios'" class="corner">
<img src="" data-ls-attrs="src=/images/clients/ios.png?v=<?php echo APP_CACHE_BUSTER; ?>" class="avatar xs" loading="lazy" width="30" height="30" />
</div>
<div data-ls-if="{{platform.type}} === 'flutter-android'" class="corner">
<img src="" data-ls-attrs="src=/images/clients/android.png?v=<?php echo APP_CACHE_BUSTER; ?>" class="avatar xs" loading="lazy" width="30" height="30" />
</div>
</div>
<span data-ls-bind="{{platform.name}}"></span> &nbsp; <small data-ls-bind="{{platform.hostname}}{{platform.key}}"></small>
</div>
<div class="margin-bottom-tiny">
<img src="" data-ls-attrs="src=/images/clients/{{platform.type}}.png?v=<?php echo APP_CACHE_BUSTER; ?>" class="avatar pull-start margin-end" loading="lazy" width="60" height="60" />
<span data-ls-bind="{{platform.name}}"></span>
</div>
<p class="margin-bottom-no desktops-only"><small data-ls-bind="{{platform.hostname}}"></small></p>
<p class="margin-bottom-no" style="margin-top: 10px;"><a href="">Get Started</a></p>
<div class="phones-only-inline tablets-only-inline margin-top-tiny">
<button class="link" data-ls-ui-trigger="platform-update-{{platform.$id}}">Update</button>
@@ -149,16 +159,19 @@ $graph = $this->getParam('graph', false);
<div class="drop-list pull-start" data-ls-ui-open="" data-button-text="Add Platform" data-button-class="button" data-blur="1" tabindex="1">
<ul>
<li>
<button class="link web-new"><img src="/images/clients/web.png?v=<?php echo APP_CACHE_BUSTER; ?>" alt="Web Platform Logo" class="avatar xs margin-end" /> New Web App</button>
<div class="link web-new"><img src="/images/clients/web.png?v=<?php echo APP_CACHE_BUSTER; ?>" alt="Web Platform Logo" class="avatar xxs margin-end-small" /> New Web App</div>
</li>
<li>
<div class="link flutter-new"><img src="/images/clients/flutter.png?v=<?php echo APP_CACHE_BUSTER; ?>" alt="Flutter Platform Logo" class="avatar xxs margin-end-small" /> New Flutter App &nbsp;<span class="text-size-tiny">(beta)</span></div>
</li>
<li class="disabled">
<button class="link ios-new"><img src="/images/clients/ios.png?v=<?php echo APP_CACHE_BUSTER; ?>" alt="iOS Platform Logo" class="avatar xs margin-end" /> New iOS App</button>
<div class="link ios-new"><img src="/images/clients/ios.png?v=<?php echo APP_CACHE_BUSTER; ?>" alt="iOS Platform Logo" class="avatar xxs margin-end-small" /> New iOS App</div>
</li>
<li class="disabled">
<button class="link android-new"><img src="/images/clients/android.png?v=<?php echo APP_CACHE_BUSTER; ?>" alt="Android Platform Logo" class="avatar xs margin-end" /> New Android App</button>
<div class="link android-new"><img src="/images/clients/android.png?v=<?php echo APP_CACHE_BUSTER; ?>" alt="Android Platform Logo" class="avatar xxs margin-end-small" /> New Android App</div>
</li>
<li class="disabled">
<button class="link unity-new"><img src="/images/clients/unity.png?v=<?php echo APP_CACHE_BUSTER; ?>" alt="Unity Platform Logo" class="avatar xs margin-end" /> New Unity Game</button>
<div class="link unity-new"><img src="/images/clients/unity.png?v=<?php echo APP_CACHE_BUSTER; ?>" alt="Unity Platform Logo" class="avatar xxs margin-end-small" /> New Unity Game</div>
</li>
</ul>
</div>
@@ -202,7 +215,7 @@ $graph = $this->getParam('graph', false);
</div>
</div>
<button type="submit">Register</button> &nbsp; <button data-ui-modal-close="" type="button" class="reverse">Cancel</button>
<button type="submit">Register</button> &nbsp; <button data-ui-modal-close="" type="button" class="reverse">Back</button>
</form>
</div>
@@ -210,7 +223,7 @@ $graph = $this->getParam('graph', false);
<form
data-analytics-event="submit"
data-analytics-category="console"
data-analytics-label="Update Project Platform"
data-analytics-label="Update Project Platform (Web)"
data-service="projects.updatePlatform"
data-scope="console"
data-event="submit"
@@ -232,6 +245,150 @@ $graph = $this->getParam('graph', false);
<hr />
<button type="submit">Update</button> &nbsp; <button data-ls-ui-trigger="modal-close" type="button" class="reverse">Cancel</button>
<button type="submit">Update</button> &nbsp; <button data-ls-ui-trigger="modal-close" type="button" class="reverse">Back</button>
</form>
</script>
<div data-ui-modal class="modal box close" data-button-alias=".flutter-new">
<button type="button" class="close pull-end" data-ui-modal-close=""><i class="icon-cancel"></i></button>
<h1 class="margin-bottom-xl">Register your Flutter App</h1>
<ul class="phases clear margin-top-negative-large padding" data-ui-phases>
<li>
<h2 style="display: none">&nbsp;&nbsp;iOS&nbsp;&nbsp;</h2>
<form
data-analytics-event="submit"
data-analytics-category="console"
data-analytics-label="Create Project Platform (Flutter / iOS)"
data-service="projects.createPlatform"
data-scope="console"
data-event="submit"
data-success="alert,trigger,reset"
data-success-param-alert-text="Registered new platform successfully"
data-success-param-trigger-events="projects.createPlatform"
data-failure="alert"
data-failure-param-alert-text="Failed to register platform"
data-failure-param-alert-classname="error">
<input type="hidden" name="projectId" data-ls-bind="{{router.params.project}}" />
<input type="hidden" name="type" data-ls-bind="flutter-ios" />
<label for="name">Name <span class="tooltip large" data-tooltip="Choose any name that will help you distinguish between your different apps."><i class="icon-question"></i></span></label>
<input type="text" class="full-width" id="name" name="name" required autocomplete="off" placeholder="My iOS App" />
<label for="key">Bundle ID <span class="tooltip large" data-tooltip="You can find your Bundle Identifier in the General tab for your app's primary target in Xcode."><i class="icon-question"></i></span></label>
<input type="text" class="full-width" id="key" name="key" required autocomplete="off" placeholder="com.company.appname" />
<hr />
<button type="submit">Register</button> &nbsp; <button data-ui-modal-close="" type="button" class="reverse">Back</button>
</form>
</li>
<li>
<h2 style="display: none">&nbsp;&nbsp;Android&nbsp;&nbsp;</h2>
<form
data-analytics-event="submit"
data-analytics-category="console"
data-analytics-label="Create Project Platform (Flutter / Android)"
data-service="projects.createPlatform"
data-scope="console"
data-event="submit"
data-success="alert,trigger,reset"
data-success-param-alert-text="Registered new platform successfully"
data-success-param-trigger-events="projects.createPlatform"
data-failure="alert"
data-failure-param-alert-text="Failed to register platform"
data-failure-param-alert-classname="error">
<input type="hidden" name="projectId" data-ls-bind="{{router.params.project}}" />
<input type="hidden" name="type" data-ls-bind="flutter-android" />
<label for="name">Name <span class="tooltip large" data-tooltip="Choose any name that will help you distinguish between your different apps."><i class="icon-question"></i></span></label>
<input type="text" class="full-width" id="name" name="name" required autocomplete="off" placeholder="My Android App" />
<label for="key">Package Name <span class="tooltip large" data-tooltip="Your package name is generally the applicationId in your app-level build.gradle file."><i class="icon-question"></i></span></label>
<input type="text" class="full-width" id="key" name="key" required autocomplete="off" placeholder="com.company.appname" />
<hr />
<button type="submit">Register</button> &nbsp; <button data-ui-modal-close="" type="button" class="reverse">Back</button>
</form>
</li>
</ul>
</div>
<script type="text/html" id="template-ios-update">
<form
data-analytics-event="submit"
data-analytics-category="console"
data-analytics-label="Update Project Platform (iOS)"
data-service="projects.updatePlatform"
data-scope="console"
data-event="submit"
data-success="alert,trigger"
data-success-param-alert-text="Updated platform successfully"
data-success-param-trigger-events="projects.updatePlatform"
data-failure="alert"
data-failure-param-alert-text="Failed to update platform"
data-failure-param-alert-classname="error">
<input type="hidden" name="projectId" data-ls-bind="{{router.params.project}}" />
<input type="hidden" name="platformId" data-ls-bind="{{platform.$id}}" />
<label data-ls-attrs="for=name-{{platform.$id}}">Name <span class="tooltip large" data-tooltip="Choose any name that will help you distinguish between your different apps."><i class="icon-question"></i></span></label>
<input type="text" class="full-width" data-ls-attrs="id=name-{{platform.$id}}" name="name" required autocomplete="off" data-ls-bind="{{platform.name}}" placeholder="My Web App" />
<label data-ls-attrs="for=key-{{platform.$id}}">Bundle ID <span class="tooltip large" data-tooltip="You can find your Bundle Identifier in the General tab for your app's primary target in Xcode."><i class="icon-question"></i></span></label>
<input name="key" type="text" class="margin-bottom" autocomplete="off" placeholder="com.cpmpany.appname" data-ls-bind="{{platform.key}}" required />
<hr />
<button type="submit">Update</button> &nbsp; <button data-ls-ui-trigger="modal-close" type="button" class="reverse">Back</button>
</form>
</script>
<script type="text/html" id="template-android-update">
<form
data-analytics-event="submit"
data-analytics-category="console"
data-analytics-label="Update Project Platform (Android)"
data-service="projects.updatePlatform"
data-scope="console"
data-event="submit"
data-success="alert,trigger"
data-success-param-alert-text="Updated platform successfully"
data-success-param-trigger-events="projects.updatePlatform"
data-failure="alert"
data-failure-param-alert-text="Failed to update platform"
data-failure-param-alert-classname="error">
<input type="hidden" name="projectId" data-ls-bind="{{router.params.project}}" />
<input type="hidden" name="platformId" data-ls-bind="{{platform.$id}}" />
<label data-ls-attrs="for=name-{{platform.$id}}">Name <span class="tooltip large" data-tooltip="Choose any name that will help you distinguish between your different apps."><i class="icon-question"></i></span></label>
<input type="text" class="full-width" data-ls-attrs="id=name-{{platform.$id}}" name="name" required autocomplete="off" data-ls-bind="{{platform.name}}" placeholder="My Web App" />
<label data-ls-attrs="for=key-{{platform.$id}}">Package Name <span class="tooltip large" data-tooltip="Your package name is generally the applicationId in your app-level build.gradle file."><i class="icon-question"></i></span></label>
<input name="key" type="text" class="margin-bottom" autocomplete="off" placeholder="com.cpmpany.appname" data-ls-bind="{{platform.key}}" required />
<hr />
<button type="submit">Update</button> &nbsp; <button data-ls-ui-trigger="modal-close" type="button" class="reverse">Back</button>
</form>
</script>
<script type="text/html" id="template-flutter-ios-update">
<div data-ls-template="template-ios-update" data-type="script"></div>
</script>
<script type="text/html" id="template-flutter-android-update">
<div data-ls-template="template-ios-update" data-type="script"></div>
</script>
<script type="text/html" id="template-flutter-macos-update">
<div data-ls-template="template-macos-update" data-type="script"></div>
</script>
+20 -3
View File
@@ -34,9 +34,26 @@ $home = $this->getParam('home', '');
<ul data-ls-loop="console-projects" data-ls-as="project" data-ls-append="" class="tiles cell-3" style="visibility: hidden">
<li class="margin-bottom">
<a data-ls-attrs="href=/console/home?project={{project.$id}}" class="box">
<div data-ls-bind="{{project.name}}" class="text-one-liner margin-bottom-large text-bold">&nbsp;</div>
<i class="icon-right-open"></i>
<div data-ls-bind="{{project.name}}" class="text-one-liner margin-bottom-small text-bold">&nbsp;</div>
<ul data-ls-loop="project.platforms" data-ls-as="platform" class="clear margin-bottom" style="min-height: 30px; overflow: hidden;">
<li class="pull-start">
<div data-ls-if="{{platform.type}} === 'web'" class="corner">
<img src="" data-ls-attrs="src=/images/clients/web.png?v=<?php echo APP_CACHE_BUSTER; ?>" class="avatar xxs no-shadow" loading="lazy" width="30" height="30" />&nbsp;
</div>
<div data-ls-if="{{platform.type}} === 'flutter-ios'" class="corner">
<img src="" data-ls-attrs="src=/images/clients/ios.png?v=<?php echo APP_CACHE_BUSTER; ?>" class="avatar xxs no-shadow" loading="lazy" width="30" height="30" />&nbsp;
</div>
<div data-ls-if="{{platform.type}} === 'flutter-android'" class="corner">
<img src="" data-ls-attrs="src=/images/clients/android.png?v=<?php echo APP_CACHE_BUSTER; ?>" class="avatar xxs no-shadow" loading="lazy" width="30" height="30" />&nbsp;
</div>
</li>
</ul>
<div>
<i class="icon-right-open"></i>
</div>
</a>
</li>
</ul>
+3 -3
View File
@@ -183,7 +183,7 @@
<span data-ls-bind="{{session.client.name}}"></span> <span data-ls-bind="{{session.client.version}}"></span> on <span data-ls-bind="{{session.model}}"></span> <span data-ls-bind="{{session.OS.name}}"></span> <span data-ls-bind="{{session.OS.version}}"></span>
<div class="margin-top-small">
<img data-ls-attrs="src={{env.API}}/avatars/flags/{{session.geo.isoCode}}?width=80&height=80&project={{env.PROJECT}}" class="avatar xs margin-end-small inline" />
<img data-ls-attrs="src={{env.API}}/avatars/flags/{{session.geo.isoCode}}?width=80&height=80&project={{env.PROJECT}}" class="avatar xxs margin-end-small inline" />
<small data-ls-bind="{{session.ip}}"></small> / <small data-ls-bind="{{session.geo.country}}"></small>
</div>
</li>
@@ -238,11 +238,11 @@
<td data-title="Date: "><span data-ls-bind="{{log.time|date-time}}"></span></td>
<td data-title="Event: "><span data-ls-bind="{{log.event}}"></span></td>
<td data-title="Client: ">
<img data-ls-attrs="src={{env.API}}/avatars/browsers/{{log.client.short_name|lowercase}}?width=80&height=80&project={{env.PROJECT}},title={{log.client.name}},alt={{log.client.name}}" class="avatar xs inline margin-end-small" />
<img data-ls-attrs="src={{env.API}}/avatars/browsers/{{log.client.short_name|lowercase}}?width=80&height=80&project={{env.PROJECT}},title={{log.client.name}},alt={{log.client.name}}" class="avatar xxs inline margin-end-small" />
<span data-ls-bind="{{log.client.name}} {{log.client.version}} on {{log.model}} {{log.OS.name}} {{log.OS.version}}"></span>
</td>
<td data-title="Location: ">
<img data-ls-attrs="src={{env.API}}/avatars/flags/{{log.geo.isoCode}}?width=80&height=80&project={{env.PROJECT}}" class="avatar xs inline margin-end-small" />
<img data-ls-attrs="src={{env.API}}/avatars/flags/{{log.geo.isoCode}}?width=80&height=80&project={{env.PROJECT}}" class="avatar xxs inline margin-end-small" />
<span data-ls-bind="{{log.geo.country}}"></span>
</td>
<td data-title="IP: "><span data-ls-bind="{{log.ip}}"></span></td>
+29
View File
@@ -1,3 +1,32 @@
## 0.1.1
- Updated flutter_web_auth version
## 0.1.0
- Added examples file
- Some minor style fixes
## 0.0.14
- Using MultipartFile for file uploads
## 0.0.13
- Fix for file upload method
## 0.0.12
- Added file upload support for storage service
## 0.0.11
- Added integration with web auth plugin to support Appwrite OAuth API
## 0.0.9
- Updated deafult params
## 0.0.8
- Fixed compilation error in Client class
+55
View File
@@ -0,0 +1,55 @@
# Examples
Init your Appwrite client:
```dart
Client client = Client();
client
.setEndpoint('https://localhost/v1') // Your Appwrite Endpoint
.setProject('5e8cf4f46b5e8') // Your project ID
.setSelfSigned() // Remove in production
;
```
Create a new user and session:
```dart
Account account = Account(client);
Response user = await account.create(email: 'me@appwrite.io', password: 'password', name: 'My Name');
Response session = await account.createSession(email: 'me@appwrite.io', password: 'password');
```
Fetch user profile:
```dart
Account account = Account(client);
Response profile = await account.get();
```
Upload File:
```dart
Storage storage = Storage(client);
MultipartFile file = MultipartFile.fromFile('./path-to-file/image.jpg', filename: 'image.jpg');
storage.createFile(
file: file,
read: ['*'],
write: []
)
.then((response) {
print(response); // File uploaded!
})
.catchError((error) {
print(error.response);
});
```
All examples and API features are available at the [official Appwrite docs](https://appwrite.io/docs)
+3 -3
View File
File diff suppressed because one or more lines are too long
+1 -1
View File
File diff suppressed because one or more lines are too long
+2 -2
View File
@@ -288,7 +288,7 @@ $value=abbreviate($value,1,false,false);return $value==="0"?"N/A":$value;}).add(
return result.length;}).add("documentLabel",function($value,rule){let value=($value!==null&&$value[rule['key']]!==undefined)?$value[rule['key']]:null;switch(rule['type']){case'bool':case'boolean':return(value)?'true':'false';break;case'numeric':return(value&&value.toString)?value.toString():value;break;default:return value;break;}}).add("documentAction",function(container){let collection=container.get('project-collection');let document=container.get('project-document');if(collection&&document&&!document.$id){return'database.createDocument';}
return'database.updateDocument';}).add("documentSuccess",function(container){let document=container.get('project-document');if(document&&!document.$id){return',redirect';}
return'';}).add("firstElement",function($value){if($value&&$value[0]){return $value[0];}
return $value;});function abbreviate(number,maxPlaces,forcePlaces,forceLetter){number=Number(number);forceLetter=forceLetter||false;if(forceLetter!==false){return annotate(number,maxPlaces,forcePlaces,forceLetter);}
return $value;}).add("platformsLimit",function($value){console.log('test console');console.log($value);return $value;});function abbreviate(number,maxPlaces,forcePlaces,forceLetter){number=Number(number);forceLetter=forceLetter||false;if(forceLetter!==false){return annotate(number,maxPlaces,forcePlaces,forceLetter);}
let abbr;if(number>=1e12){abbr="T";}else if(number>=1e9){abbr="B";}else if(number>=1e6){abbr="M";}else if(number>=1e3){abbr="K";}else{abbr="";}
return annotate(number,maxPlaces,forcePlaces,abbr);}
function annotate(number,maxPlaces,forcePlaces,abbr){let rounded=0;switch(abbr){case"T":rounded=number/1e12;break;case"B":rounded=number/1e9;break;case"M":rounded=number/1e6;break;case"K":rounded=number/1e3;break;case"":rounded=number;break;}
@@ -402,7 +402,7 @@ if(buttonSelector){let buttonElements=element.querySelectorAll(buttonSelector);b
element.addEventListener('click',function(event){let targetA=findParent('a',event.target);let targetB=findParent('button',event.target);if(!targetA&&!targetB){return false;}
if(targetA&&!targetA.href){return false;}
if(targetB&&!targetB.classList.contains('link')){return false;}
closeDelay();});element.insertBefore(button,element.firstChild);}});})(window);(function(window){window.ls.container.get("view").add({selector:"data-ui-phases",controller:function(element,window,document,expression,router){var tabs=document.createElement("ul");var container=document.createElement("div");var titles=Array.prototype.slice.call(element.getElementsByTagName("h2"));var next=Array.prototype.slice.call(element.querySelectorAll("[data-next]"));var previous=Array.prototype.slice.call(element.querySelectorAll("[data-previous]"));var position=0;var init=false;for(var i=0;i<element.children.length;i++){var tabState=expression.parse(element.children[i].dataset["state"]||"");if(tabState===(window.location.pathname+window.location.search).substring(0,tabState.length)){position=i;}}
closeDelay();});element.insertBefore(button,element.firstChild);}});})(window);(function(window){window.ls.container.get("view").add({selector:"data-ui-phases",controller:function(element,window,document,expression,router){var tabs=document.createElement("ul");var container=document.createElement("div");var titles=Array.prototype.slice.call(element.getElementsByTagName("h2"));var next=Array.prototype.slice.call(element.querySelectorAll("[data-next]"));var previous=Array.prototype.slice.call(element.querySelectorAll("[data-previous]"));var position=0;var init=false;for(var i=0;i<element.children.length;i++){var tabState=expression.parse(element.children[i].dataset["state"]||"");if(tabState&&tabState===(window.location.pathname+window.location.search).substring(0,tabState.length)){position=i;}}
var setTab=function(index){var tabState=expression.parse(element.children[index].dataset["state"]||"");var url="";if(tabState!==""&&tabState!==window.location.pathname+window.location.search){var parser=document.createElement("a");parser.href=tabState;url=!init?parser.pathname+window.location.search:tabState;if(position!=index){window.history.pushState({},"",url);router.reset();}}
element.children[position].classList.remove("selected");element.children[index].classList.add("selected");tabs.children[position].classList.remove("selected");tabs.children[index].classList.add("selected");position=index;document.dispatchEvent(new CustomEvent("tab-changed"));init=true;};tabs.classList.add("tabs");container.classList.add("container");container.classList.add("close");container.dataset["lsUiOpen"]="";container.dataset["buttonClass"]="icon icon-down-dir";titles.map(function(obj,i){var title=document.createElement("li");title.innerHTML=obj.innerHTML;title.className=obj.className;title.tabIndex=0;tabs.appendChild(title);title.addEventListener("click",function(){setTab(i);});title.addEventListener("keyup",function(){if(event.which===13){setTab(i);}});});next.map(function(obj){obj.addEventListener("click",function(){setTab(position+1);});});previous.map(function(obj){obj.addEventListener("click",function(){setTab(position-1);});});setTab(position);container.appendChild(tabs);element.parentNode.insertBefore(container,element);}});})(window);(function(window){window.ls.container.get("view").add({selector:"data-ls-ui-trigger",controller:function(element,document,expression){let trigger=expression.parse(element.dataset["lsUiTrigger"]||'').trim().split(',');let event=expression.parse(element.dataset["event"]||'click');let debug=element.getAttribute('data-debug')||false;for(let index=0;index<trigger.length;index++){let name=trigger[index];element.addEventListener(event,function(){if(debug){console.log('Debug: event triggered: '+name);}
document.dispatchEvent(new CustomEvent(name));});}}});})(window);
+1 -1
View File
File diff suppressed because one or more lines are too long
+1 -1
View File
File diff suppressed because one or more lines are too long
Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

+1 -1
View File
@@ -1088,4 +1088,4 @@ window.ls.container.get('view').add({
}
}
}
});
});
File diff suppressed because one or more lines are too long
+7
View File
@@ -414,6 +414,13 @@ window.ls.filter
return $value[0];
}
return $value;
})
.add("platformsLimit", function($value) {
console.log('test console');
console.log($value);
return $value;
})
;
+2 -8
View File
@@ -21,13 +21,7 @@
element.children[i].dataset["state"] || ""
);
if (
tabState ===
(window.location.pathname + window.location.search).substring(
0,
tabState.length
)
) {
if (tabState && tabState === (window.location.pathname + window.location.search).substring(0, tabState.length)) {
position = i;
}
}
@@ -100,7 +94,7 @@
setTab(position - 1);
});
});
setTab(position);
container.appendChild(tabs);
+19
View File
@@ -1,3 +1,13 @@
.avatar-container {
position: relative;
.corner {
position: absolute;
bottom: -3px;
.func-end(-3px);
}
}
.avatar {
width: 60px;
height: 60px;
@@ -28,7 +38,16 @@
background: transparent;
}
.no-shadow {
box-shadow: none;
}
&.xs {
width: 30px;
height: 30px;
}
&.xxs {
width: 20px;
height: 20px;
}

Some files were not shown because too many files have changed in this diff Show More