- {#if $organization.billingPlan === BillingPlan.SCALE}
+ {#if $currentPlan?.backupPolicies > 1}
{#if title || subtitle}
{#if title}
@@ -195,7 +194,7 @@
{/if}
- {#if $organization.billingPlan === BillingPlan.PRO}
+ {#if $currentPlan?.backupPolicies === 1}
{@const dailyPolicy = $presetPolicies[1]}
{#if isFromBackupsTab}
diff --git a/src/routes/(console)/project-[region]-[project]/databases/database-[database]/table-[table]/indexes/createIndex.svelte b/src/routes/(console)/project-[region]-[project]/databases/database-[database]/table-[table]/indexes/createIndex.svelte
index 88af9c257..f706ab739 100644
--- a/src/routes/(console)/project-[region]-[project]/databases/database-[database]/table-[table]/indexes/createIndex.svelte
+++ b/src/routes/(console)/project-[region]-[project]/databases/database-[database]/table-[table]/indexes/createIndex.svelte
@@ -71,7 +71,8 @@
// spatial type selected -> reset column list to single empty column
// and the column already is not spatial type
$effect(() => {
- if (selectedType === IndexType.Spatial && !columnList.at(0).value) {
+ const firstColumn = $table.columns.find((col) => col.key === columnList.at(0)?.value);
+ if (selectedType === IndexType.Spatial && firstColumn && !isSpatialType(firstColumn)) {
columnList = [{ value: '', order: null, length: null }];
}
});
diff --git a/src/routes/(console)/project-[region]-[project]/databases/database-[database]/table-[table]/layout/emptySheet.svelte b/src/routes/(console)/project-[region]-[project]/databases/database-[database]/table-[table]/layout/emptySheet.svelte
index e3d832a8a..c77dd08d8 100644
--- a/src/routes/(console)/project-[region]-[project]/databases/database-[database]/table-[table]/layout/emptySheet.svelte
+++ b/src/routes/(console)/project-[region]-[project]/databases/database-[database]/table-[table]/layout/emptySheet.svelte
@@ -251,6 +251,7 @@
data-mode={mode}
bind:this={spreadsheetContainer}
class:custom-columns={customColumns.length > 0}
+ class:no-custom-columns={customColumns.length <= 0}
class="databases-spreadsheet spreadsheet-container-outer">
.spreadsheet-fade-bottom {
+ top: var(--top-actions-spacing) !important;
+ background: var(--bgcolor-neutral-primary) !important;
+ }
+ }
+ }
+
&:not(.custom-columns) :global(.spreadsheet-container) {
overflow-x: hidden;
overflow-y: hidden;
@@ -393,12 +407,16 @@
}
&[data-mode='rows'] {
+ --top-actions-spacing: 50%;
+
& :global([role='rowheader'] :nth-last-child(2) [role='presentation']) {
display: none;
}
}
&[data-mode='indexes'] {
+ --top-actions-spacing: 40%;
+
& :global([role='cell']:last-child [role='presentation']) {
display: none;
}
@@ -463,4 +481,11 @@
margin-bottom: 15%;
}
}
+
+ @media (max-width: 768px) {
+ // global but controlled properly!
+ :global(main:has(.no-custom-columns) .console-container) {
+ opacity: 0;
+ }
+ }
diff --git a/src/routes/(console)/project-[region]-[project]/functions/create-function/deploy/+page.svelte b/src/routes/(console)/project-[region]-[project]/functions/create-function/deploy/+page.svelte
index 37f06d174..bd1038880 100644
--- a/src/routes/(console)/project-[region]-[project]/functions/create-function/deploy/+page.svelte
+++ b/src/routes/(console)/project-[region]-[project]/functions/create-function/deploy/+page.svelte
@@ -11,7 +11,7 @@
import { Fieldset, Layout, Icon, Input, Tag } from '@appwrite.io/pink-svelte';
import { IconGithub, IconPencil } from '@appwrite.io/pink-icons-svelte';
import { onMount } from 'svelte';
- import { ID, Runtime } from '@appwrite.io/console';
+ import { ID, Runtime, Type } from '@appwrite.io/console';
import { CustomId } from '$lib/components';
import { getIconFromRuntime } from '$lib/stores/runtimes';
import { regionalConsoleVariables } from '$routes/(console)/project-[region]-[project]/store';
@@ -135,7 +135,8 @@
repository: data.repository.name,
owner: data.repository.owner,
rootDirectory: rootDir || '.',
- version: latestTag ?? '1.0.0',
+ type: Type.Tag,
+ reference: latestTag ?? '1.0.0',
activate: true
});
diff --git a/src/routes/(console)/project-[region]-[project]/functions/create-function/template-[template]/+page.svelte b/src/routes/(console)/project-[region]-[project]/functions/create-function/template-[template]/+page.svelte
index 0f09e10b7..59727f61f 100644
--- a/src/routes/(console)/project-[region]-[project]/functions/create-function/template-[template]/+page.svelte
+++ b/src/routes/(console)/project-[region]-[project]/functions/create-function/template-[template]/+page.svelte
@@ -15,7 +15,7 @@
import { writable } from 'svelte/store';
import ProductionBranch from '$lib/components/git/productionBranchFieldset.svelte';
import Configuration from './configuration.svelte';
- import { ID, Runtime, type Models } from '@appwrite.io/console';
+ import { ID, Runtime, Type, type Models } from '@appwrite.io/console';
import {
ConnectBehaviour,
NewRepository,
@@ -180,7 +180,8 @@
repository: data.template.providerRepositoryId || undefined,
owner: data.template.providerOwner || undefined,
rootDirectory: rt?.providerRootDirectory || undefined,
- version: data.template.providerVersion || undefined,
+ type: Type.Tag,
+ reference: data.template.providerVersion || undefined,
activate: true
});
diff --git a/src/routes/(console)/project-[region]-[project]/functions/function-[function]/+page.ts b/src/routes/(console)/project-[region]-[project]/functions/function-[function]/+page.ts
index d5b08e19f..13561dd09 100644
--- a/src/routes/(console)/project-[region]-[project]/functions/function-[function]/+page.ts
+++ b/src/routes/(console)/project-[region]-[project]/functions/function-[function]/+page.ts
@@ -1,4 +1,4 @@
-import { Query } from '@appwrite.io/console';
+import { Query, type Models } from '@appwrite.io/console';
import { sdk } from '$lib/stores/sdk';
import { getLimit, getPage, getQuery, pageToOffset } from '$lib/helpers/load';
import { Dependencies, PAGE_LIMIT } from '$lib/constants';
@@ -15,17 +15,27 @@ export const load: PageLoad = async ({ params, depends, url, route, parent }) =>
const parsedQueries = queryParamToMap(query || '[]');
queries.set(parsedQueries);
+ let activeDeployment: Models.Deployment | null = null;
+ if (data.function.deploymentId) {
+ try {
+ activeDeployment = await sdk
+ .forProject(params.region, params.project)
+ .functions.getDeployment({
+ functionId: params.function,
+ deploymentId: data.function.deploymentId
+ });
+ } catch (error) {
+ // active deployment with the requested ID could not be found
+ activeDeployment = null;
+ }
+ }
+
return {
offset,
limit,
query,
installations: data.installations,
- activeDeployment: data.function.deploymentId
- ? await sdk.forProject(params.region, params.project).functions.getDeployment({
- functionId: params.function,
- deploymentId: data.function.deploymentId
- })
- : null,
+ activeDeployment,
deploymentList: await sdk
.forProject(params.region, params.project)
.functions.listDeployments({
@@ -41,7 +51,15 @@ export const load: PageLoad = async ({ params, depends, url, route, parent }) =>
'buildDuration',
'status',
'type',
- 'resourceId'
+ 'resourceId',
+ 'providerRepositoryUrl',
+ 'providerRepositoryOwner',
+ 'providerRepositoryName',
+ 'providerBranchUrl',
+ 'providerBranch',
+ 'providerCommitMessage',
+ 'providerCommitHash',
+ 'providerCommitUrl'
]),
...parsedQueries.values()
]
diff --git a/src/routes/(console)/project-[region]-[project]/overview/(components)/create.svelte b/src/routes/(console)/project-[region]-[project]/overview/(components)/create.svelte
index 84e6a7809..4c9bb8150 100644
--- a/src/routes/(console)/project-[region]-[project]/overview/(components)/create.svelte
+++ b/src/routes/(console)/project-[region]-[project]/overview/(components)/create.svelte
@@ -24,8 +24,8 @@
let isSubmitting = writable(false);
let scopes: string[] = [];
- let name = '',
- expire = '';
+ let name = '';
+ let expire: string | null = null;
async function create() {
try {
diff --git a/src/routes/(console)/project-[region]-[project]/overview/api-keys/scopes.svelte b/src/routes/(console)/project-[region]-[project]/overview/api-keys/scopes.svelte
index 877db1b18..48485cc31 100644
--- a/src/routes/(console)/project-[region]-[project]/overview/api-keys/scopes.svelte
+++ b/src/routes/(console)/project-[region]-[project]/overview/api-keys/scopes.svelte
@@ -26,17 +26,16 @@
+
+
diff --git a/src/routes/(console)/project-[region]-[project]/overview/platforms/createAndroid.svelte b/src/routes/(console)/project-[region]-[project]/overview/platforms/createAndroid.svelte
index 9ad7963e1..3abd55aa9 100644
--- a/src/routes/(console)/project-[region]-[project]/overview/platforms/createAndroid.svelte
+++ b/src/routes/(console)/project-[region]-[project]/overview/platforms/createAndroid.svelte
@@ -17,7 +17,7 @@
import { Card } from '$lib/components';
import { page } from '$app/state';
import { onMount } from 'svelte';
- import { realtime, sdk } from '$lib/stores/sdk';
+ import { getApiEndpoint, realtime, sdk } from '$lib/stores/sdk';
import { Submit, trackError, trackEvent } from '$lib/actions/analytics';
import { addNotification } from '$lib/stores/notifications';
import { fade } from 'svelte/transition';
@@ -26,6 +26,7 @@
import { PlatformType } from '@appwrite.io/console';
import { project } from '../../store';
import { getCorrectTitle, type PlatformProps } from './store';
+ import LlmBanner from './llmBanner.svelte';
let { isConnectPlatform = false }: PlatformProps = $props();
@@ -35,6 +36,60 @@
let isPlatformCreated = $state(isConnectPlatform);
const projectId = page.params.project;
+ const VERSIONS_ENDPOINT = (() => {
+ const endpoint = getApiEndpoint(page.params.region);
+ const url = new URL('/versions', endpoint);
+ return url.toString();
+ })();
+ let androidSdkVersion = $state('11.3.0');
+
+ function buildAndroidInstructions(version: string) {
+ return `
+Confirm you're working inside the correct Android project before editing anything:
+- Navigate into the directory that contains the real Android app module (look for gradlew, settings.gradle, and the app-level build.gradle(.kts)).
+- If Cursor opens in a parent folder (like your home directory) or you see multiple Android projects, ask which one to modify before making changes.
+- Update the app-level build.gradle.kts by default, but be ready to edit a Groovy build.gradle if the project hasn't migrated to Kotlin DSL yet.
+
+Prefer Version Catalogs when adding the Appwrite SDK:
+1. If ./gradle/libs.versions.toml exists, add or reuse an Appwrite entry:
+\`\`\`toml
+[libraries]
+appwrite = { module = "io.appwrite:sdk-for-android", version = "${version}" }
+\`\`\`
+2. Reference it inside the module's dependencies block:
+\`\`\`kotlin
+dependencies {
+ implementation(libs.appwrite)
+}
+\`\`\`
+Only when the project lacks ./gradle/libs.versions.toml should you hardcode the dependency:
+\`\`\`kotlin
+implementation("io.appwrite:sdk-for-android:${version}")
+\`\`\`
+Legacy Groovy scripts should use:
+\`\`\`groovy
+implementation "io.appwrite:sdk-for-android:${version}"
+\`\`\`
+
+Before introducing any new files, search the project (app/src, libs/, shared modules, etc.) for existing Appwrite client helpers (look for \`Client(\`, \`AppwriteClient\`, or \`.setEndpoint\`). If a client already exists, update its configuration instead of creating a duplicate.
+
+Ensure the Appwrite client is initialized with the application context and current project info:
+\`\`\`kotlin
+val client = Client(applicationContext)
+ .setEndpoint("${sdk.forProject(page.params.region, page.params.project).client.config.endpoint}")
+ .setProject("${projectId}")
+
+val account = Account(client)
+\`\`\`
+
+From the app's entry point (e.g., Application class or the first launched Activity), automatically invoke a helper that pings Appwrite so the user can verify connectivity and will be reflected on the Appwrite console:
+\`\`\`kotlin
+client.ping()
+\`\`\`
+`;
+ }
+
+ const alreadyExistsInstructions = $derived(buildAndroidInstructions(androidSdkVersion));
const gitCloneCode =
'\ngit clone https://github.com/appwrite/starter-for-android\ncd starter-for-android\n';
@@ -43,6 +98,22 @@
const val APPWRITE_PROJECT_NAME = "${$project.name}"
const val APPWRITE_PUBLIC_ENDPOINT = "${sdk.forProject(page.params.region, page.params.project).client.config.endpoint}"`;
+ async function fetchAndroidSdkVersion() {
+ try {
+ const response = await fetch(VERSIONS_ENDPOINT);
+ if (!response.ok) {
+ throw new Error(`Failed to fetch versions: ${response.status}`);
+ }
+ const data = await response.json();
+ const latestVersion = data?.['client-android'];
+ if (typeof latestVersion === 'string' && latestVersion.trim()) {
+ androidSdkVersion = latestVersion.trim();
+ }
+ } catch (error) {
+ console.error('Unable to fetch latest Android SDK version', error);
+ }
+ }
+
async function createAndroidPlatform() {
try {
isCreatingPlatform = true;
@@ -83,6 +154,7 @@ const val APPWRITE_PUBLIC_ENDPOINT = "${sdk.forProject(page.params.region, page.
}
onMount(() => {
+ fetchAndroidSdkVersion();
const unsubscribe = realtime.forConsole(page.params.region, 'console', (response) => {
if (response.events.includes(`projects.${projectId}.ping`)) {
connectionSuccessful = true;
@@ -171,6 +243,12 @@ const val APPWRITE_PUBLIC_ENDPOINT = "${sdk.forProject(page.params.region, page.
{#if isPlatformCreated}