Android Example [B4X] AS FeatureRequest - Supabase as backend


In this example I show you how to use supabase as a backend for the AS_FeatureRequest quickly and easily.

Supabase
1. Create tables
replace YourAppName with your app name
Create FeatureRequest table:
create table
  public."dt_FeatureRequest_YourAppName" (
    "Id" bigint generated by default as identity not null,
    "CreatedAt" timestamp with time zone not null default now(),
    "Title" text not null,
    "Description" text null,
    "isPremiumFeature" boolean null default false,
    "Status" integer null default 0,
    "ImplementedVersion" text null,
    constraint dt_FeatureRequest_YourAppName_pkey primary key ("Id")
  ) tablespace pg_default;
Create user vote table:
create table
  public."dt_FeatureRequestUserUpvotes_YourAppName" (
    "Id" bigint generated by default as identity not null,
    "CreatedAt" timestamp with time zone not null default now(),
    "UserId" uuid not null default auth.uid (),
    "FeatureRequest_YourAppName_Id" bigint not null,
    "isUpvote" boolean not null,
    constraint dt_FeatureRequestUserUpvotes_YourAppName_pkey primary key ("UserId", "FeatureRequest_YourAppName_Id"),
    constraint dt_FeatureRequestUserUpvotes_Log_FeatureRequest_YourAppName_Id_fkey foreign key ("FeatureRequest_YourAppName_Id") references "dt_FeatureRequest_YourAppName" ("Id") on delete cascade
  ) tablespace pg_default;
The constraint prevents the same user from voting for the same feature several times at database level, the AS_FeatureRequest already takes this into account, but still save it again at database level.

2. Activate anonymous login in the supabase settings:
1728689290436.png

read more:

3. Add RLS roles

Role for dt_FeatureRequest_YourAppName
1728689522224.png

Roles for dt_FeatureRequestUserUpvotes_YourAppName
1728689580001.png
1728689598258.png


4. Create RPC function to select the data we need
B4X:
CREATE
OR REPLACE FUNCTION GetFeatureRequests () RETURNS TABLE (
  Id BIGINT,
  CreatedAt TIMESTAMP WITH TIME ZONE,
  Title TEXT,
  Description TEXT,
  isPremiumFeature BOOLEAN,
  Status INTEGER,
  ImplementedVersion TEXT,
  VoteCount BIGINT,
  UserVoteStatus INTEGER
) AS $$
BEGIN
    RETURN QUERY
    SELECT
        fr."Id",
        fr."CreatedAt",
        fr."Title",
        fr."Description",
        fr."isPremiumFeature",
        fr."Status",
        fr."ImplementedVersion",
        COALESCE(SUM(CASE
                      WHEN u."isUpvote" = true THEN 1
                      WHEN u."isUpvote" = false THEN -1
                      ELSE 0
                    END), 0) AS VoteCount,
        COALESCE(MAX(CASE
                      WHEN u."UserId" = auth.uid() AND u."isUpvote" = true THEN 1
                      WHEN u."UserId" = auth.uid() AND u."isUpvote" = false THEN 0
                      ELSE -1
                    END), -1) AS UserVoteStatus
    FROM
        public."dt_FeatureRequest_Lognote" fr
    LEFT JOIN
        public."dt_FeatureRequestUserUpvotes_Lognote" u
    ON
        u."FeatureRequest_Lognote_Id" = fr."Id"
    GROUP BY
        fr."Id", fr."CreatedAt", fr."Title", fr."Description",
        fr."isPremiumFeature", fr."Status", fr."ImplementedVersion"
    ORDER BY
        VoteCount DESC,
        fr."CreatedAt" DESC;
END;
$$ LANGUAGE plpgsql;

5. Sample data
B4X:
INSERT INTO
"public"."dt_FeatureRequest_Lognote"
("Id",
"CreatedAt",
"Title",
"Description",
"isPremiumFeature",
"Status",
"ImplementedVersion"
)
VALUES
('1',
'2024-10-08 13:12:53.772772+00',
'Face ID Support',
'The user should be able to lock all or specific groups. Only viewable after successfull Face ID unlock.',
'true',
'0',
null);

Client
Initialize supabase and create anon user:
    xSupabase.Initialize("https://xxx.supabase.co","xxx")
    xSupabase.InitializeEvents(Me,"Supabase")
 
    'creates a new anon user if it has not yet been created for the current device
    Wait For (xSupabase.Auth.isUserLoggedIn) Complete (isLoggedIn As Boolean)
 
    If isLoggedIn = False Then
    
        Wait For (xSupabase.Auth.LogIn_Anonymously) Complete (AnonymousUser As SupabaseUser)
        If AnonymousUser.Error.Success Then
            Log("Successfully created an anonymous user")
        Else
            Log("Error: " & AnonymousUser.Error.ErrorMessage)
        End If
 
    End If
 
    LoadOpenRequests
Load feature requests from supabase:
Private Sub LoadOpenRequests
 
    Dim CallFunction As Supabase_DatabaseRpc = xSupabase.Database.CallFunction
    CallFunction.Rpc("GetFeatureRequests".ToLowerCase)
    Wait For (CallFunction.Execute) Complete (RpcResult As SupabaseRpcResult)
 
    AS_FeatureRequest1.Clear 'Clears the list
 
    If RpcResult.Error.Success Then
        'Log(RpcResult.Data)
    
        Dim parser As JSONParser
        parser.Initialize(RpcResult.Data)
        Dim jRoot As List = parser.NextArray
        For Each Row As Map In jRoot
        
            Dim StatusText As String = ""
            Select Row.Get("status")
                Case 0
                    StatusText = "Submitted"
                Case 1
                    StatusText = "Planned"
                Case 2
                    StatusText = "In Development"
                Case 3
                    StatusText = "Testing"
                Case 4
                    StatusText = "Done"
            End Select
        
            Dim lstChips As List : lstChips.Initialize
            lstChips.Add(AS_FeatureRequest1.CreateItemChip(StatusText,xui.Color_ARGB(255,45, 136, 121),xui.Color_White))
            If Row.Get("ispremiumfeature") Then lstChips.Add(AS_FeatureRequest1.CreateItemChip("Premium",xui.Color_ARGB(255,141, 68, 173),xui.Color_White))
        
            AS_FeatureRequest1.AddItem(Row.Get("title"),Row.Get("description"),lstChips,AS_FeatureRequest1.UserVoteStatus2Text(Row.Get("uservotestatus")),Row.Get("votecount"),Row.Get("id"))
            
        Next
    
    End If
 
End Sub
Insert a new user vote:
Private Sub AS_FeatureRequest1_Voted(isUpvote As Boolean,Value As Object)
    Dim Insert As Supabase_DatabaseInsert = xSupabase.Database.InsertData
    Insert.From("dt_FeatureRequestUserUpvotes_Lognote")
    Dim InsertMap As Map = CreateMap("FeatureRequest_Lognote_Id":Value,"isUpvote":isUpvote)
    Wait For (Insert.Insert(InsertMap).Execute) Complete (Result As SupabaseDatabaseResult)
    Log(Result.Error.ErrorMessage)
End Sub
 

Attachments

  • AS_FeatureRequest Supabase Example.zip
    178.9 KB · Views: 65
Last edited:
Top