WIP Browser example; WIP init API; Partial update keys API
This commit is contained in:
parent
27a0d9dba1
commit
80f9b7e76a
|
@ -1,12 +1,12 @@
|
|||
image: debian:latest
|
||||
|
||||
before_script: |
|
||||
sh ./Tools/InstallBuildEnvironment.sh
|
||||
bash ./Tools/InstallBuildEnvironment.sh
|
||||
|
||||
Tests:
|
||||
stage: build
|
||||
script: |
|
||||
. .env
|
||||
source .env
|
||||
make -j$(nproc --all)
|
||||
rules:
|
||||
- if: $CI_COMMIT_REF_NAME == $CI_DEFAULT_BRANCH
|
||||
|
|
|
@ -0,0 +1,133 @@
|
|||
#include "../../LibMultiSpacc/MultiSpacc.h"
|
||||
#include <dirent.h>
|
||||
|
||||
#define AppName "Browser"
|
||||
#define TilesImgFile "./Assets/CHARS.png"
|
||||
|
||||
#define TileSize 8
|
||||
#define ScreenTilesH (windowConfig.width / TileSize)
|
||||
|
||||
MultiSpacc_KeysStates buttonsStates;
|
||||
MultiSpacc_SurfaceConfig windowConfig = {0};
|
||||
MultiSpacc_Window *window;
|
||||
MultiSpacc_Surface *screen;
|
||||
MultiSpacc_Surface *tilesImg;
|
||||
|
||||
struct dirent *de;
|
||||
DIR *dr;
|
||||
|
||||
bool TryReadDirectory( char path[] )
|
||||
{
|
||||
int i = 0;
|
||||
char previousPath[1024];
|
||||
char workingPath[1024];
|
||||
char displayPath[ScreenTilesH+1];
|
||||
|
||||
memset( displayPath, 0, ScreenTilesH+1 );
|
||||
|
||||
if( dr != NULL ){
|
||||
closedir(dr);
|
||||
}
|
||||
|
||||
if( (dr = opendir(path)) != NULL ){
|
||||
strcpy( previousPath, path );
|
||||
}
|
||||
else{
|
||||
dr = opendir(previousPath);
|
||||
}
|
||||
|
||||
if( strlen(getcwd( workingPath, sizeof(workingPath) )) > ScreenTilesH )
|
||||
{
|
||||
strncpy( displayPath, "...", 3 );
|
||||
i = 3;
|
||||
}
|
||||
|
||||
// TODO: fix bug, if path is too short we have parts of it to the right
|
||||
while( workingPath[i] )
|
||||
{
|
||||
if( strlen(workingPath) - ScreenTilesH <= i-3 )
|
||||
{
|
||||
strcat( displayPath, &workingPath[i] );
|
||||
}
|
||||
++i;
|
||||
}
|
||||
|
||||
SDL_FillRect( screen, &screen->clip_rect, SDL_MapRGB( screen->format, 0, 0, 0 ) );
|
||||
MultiSpacc_PrintText( displayPath, screen, &windowConfig, 0, 0, tilesImg );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool RealUpdate( void *args, double deltaTime )
|
||||
{
|
||||
int entriesCount = 0;
|
||||
|
||||
MultiSpacc_PollButtons( 0, &buttonsStates );
|
||||
|
||||
// TODO: show cursor, allow moving it in list and to select entries
|
||||
if( MultiSpacc_CheckKeyPress( MultiSpacc_Key_Confirm, &buttonsStates ) )
|
||||
{
|
||||
chdir("..");
|
||||
TryReadDirectory(".");
|
||||
}
|
||||
else if( MultiSpacc_CheckKeyPress( MultiSpacc_Key_Up, &buttonsStates ) )
|
||||
{
|
||||
|
||||
}
|
||||
else if( MultiSpacc_CheckKeyPress( MultiSpacc_Key_Down, &buttonsStates ) )
|
||||
{
|
||||
|
||||
}
|
||||
// TODO: listen for OS terminate signal
|
||||
else if( MultiSpacc_CheckKeyPress( MultiSpacc_Key_Pause, &buttonsStates ) )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
de = readdir(dr); // "delete" first entry (".", meaning current directory) from list
|
||||
while ( (de = readdir(dr)) != NULL )
|
||||
{
|
||||
MultiSpacc_PrintText( de->d_name, screen, &windowConfig, 2, 2+i, tilesImg );
|
||||
++i;
|
||||
}
|
||||
// TODO: handle directories with more entries than screen height
|
||||
|
||||
if( !MultiSpacc_UpdateDisplay(window) )
|
||||
{
|
||||
MultiSpacc_PrintDebug("[E] Error Updating Screen.\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int main( int argc, char *argv[] )
|
||||
{
|
||||
if( !MultiSpacc_InitSystem() )
|
||||
{
|
||||
MultiSpacc_PrintDebug("[E] Error Initializing System Core.\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
window = MultiSpacc_SetWindow( &windowConfig );
|
||||
screen = MultiSpacc_GetWindowSurface( window );
|
||||
if( window == NULL || screen == NULL )
|
||||
{
|
||||
MultiSpacc_PrintDebug("[E] Error Initializing Video System.\n");
|
||||
return -1;
|
||||
};
|
||||
|
||||
// Bitmap font forked from: <https://github.com/nesdoug/01_Hello/blob/master/Alpha.chr>
|
||||
// Original copyright (c) 2018 Doug Fraker www.nesdoug.com (MIT)
|
||||
tilesImg = MultiSpacc_LoadImage( TilesImgFile, screen, NULL );
|
||||
if( tilesImg == NULL )
|
||||
{
|
||||
MultiSpacc_PrintDebug("[E] Error Loading tilesImg (%s).\n", TilesImgFile);
|
||||
return -1;
|
||||
}
|
||||
|
||||
TryReadDirectory(".");
|
||||
MultiSpacc_SetAppTitle( window, AppName );
|
||||
MultiSpacc_PrintDebug("[I] Ready!\n");
|
||||
return MultiSpacc_SetMainLoop( NULL, RealUpdate, NULL );
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
include ../Common.mk
|
|
@ -0,0 +1,18 @@
|
|||
#include "../../LibMultiSpacc/MultiSpacc.h"
|
||||
|
||||
#define AppName "Clock"
|
||||
|
||||
|
||||
|
||||
int main( int argc, char *argv[] )
|
||||
{
|
||||
// ... do setup things
|
||||
|
||||
if( !MultiSpacc_SystemClockAvailable )
|
||||
{
|
||||
// ... make the user set time in-app
|
||||
}
|
||||
|
||||
// ... retrieve system time by common API or keep a clock manually
|
||||
// ... display and update a clock
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
include ../Common.mk
|
|
@ -88,6 +88,8 @@ int main( int argc, char *argv[] )
|
|||
windowConfig.height = 240;
|
||||
memcpy( windowConfig.palette, palette, 32 );
|
||||
|
||||
MultiSpacc_InitSystem();
|
||||
// TODO: integrate into LibMultiSpacc and make cross-platform to change into current directory
|
||||
//romfsInit();
|
||||
//chdir("romfs:/");
|
||||
|
||||
|
@ -109,6 +111,7 @@ int main( int argc, char *argv[] )
|
|||
margs.tilesImg = MultiSpacc_LoadImage( "./Assets/CHARS.png", margs.background, NULL );
|
||||
if( margs.tilesImg == NULL )
|
||||
{
|
||||
MultiSpacc_PrintDebug("[E] Error Loading tilesImg (%s).\n", TilesImgFile);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
#include "../../LibMultiSpacc/MultiSpacc.h"
|
||||
|
||||
#define AppName "Pong"
|
||||
|
||||
#define iabs(x) (((x) >= 0) ? (x) : -(x))
|
||||
#define maxOf2(a, b) (((a + b) / 2) + (iabs(a - b) / 2))
|
||||
|
||||
#define AppName "Pong"
|
||||
|
||||
bool paused = false;
|
||||
int scoreSx = 0;
|
||||
int scoreDx = 0;
|
||||
|
@ -322,6 +322,7 @@ int main( int argc, char *argv[] )
|
|||
windowConfig.height = 240;
|
||||
memcpy( windowConfig.palette, palette, 32 );
|
||||
|
||||
MultiSpacc_InitSystem();
|
||||
window = MultiSpacc_SetWindow( &windowConfig );
|
||||
screen = MultiSpacc_GetWindowSurface( window );
|
||||
background = MultiSpacc_CreateSurface( &windowConfig );
|
||||
|
@ -332,13 +333,13 @@ int main( int argc, char *argv[] )
|
|||
};
|
||||
|
||||
MultiSpacc_SetAppTitle( window, AppName );
|
||||
MultiSpacc_PrintDebug("[I] Ready!\n");
|
||||
|
||||
// Bitmap font forked from: <https://github.com/nesdoug/01_Hello/blob/master/Alpha.chr>
|
||||
// Original copyright (c) 2018 Doug Fraker www.nesdoug.com (MIT)
|
||||
tilesImg = MultiSpacc_LoadImage( "./Assets/CHARS.png", screen, NULL );
|
||||
if( tilesImg == NULL )
|
||||
{
|
||||
MultiSpacc_PrintDebug("[E] Error Loading tilesImg (%s).\n", TilesImgFile);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -347,5 +348,6 @@ int main( int argc, char *argv[] )
|
|||
paddleSxY = windowConfig.height/2 - PaddleHeightPx;
|
||||
paddleDxY = windowConfig.height/2 - PaddleHeightPx;
|
||||
|
||||
MultiSpacc_PrintDebug("[I] Ready!\n");
|
||||
return MultiSpacc_SetMainLoop( FixedUpdate, RealUpdate, NULL );
|
||||
}
|
||||
|
|
|
@ -1,60 +1,33 @@
|
|||
#include "./MultiSpacc.h"
|
||||
|
||||
// TODO: Handle actual presses in SDL
|
||||
// void MultiSpacc_PollButtons( char pad, MultiSpacc_KeysStates *buttonsPressed, MultiSpacc_KeysStates *buttonsHeld )
|
||||
// {
|
||||
// #if defined(MultiSpacc_Target_SDLCommon)
|
||||
// SDL_PumpEvents();
|
||||
// #if defined(MultiSpacc_Target_SDL12)
|
||||
// buttonsPressed->keysStates = SDL_GetKeyState(NULL);
|
||||
// #elif defined(MultiSpacc_Target_SDL20)
|
||||
// buttonsPressed->keysStates = SDL_GetKeyboardState(NULL);
|
||||
// #endif
|
||||
// buttonsHeld->keysStates = buttonsPressed->keysStates;
|
||||
|
||||
// #elif defined(MultiSpacc_Target_NDS)
|
||||
// scanKeys();
|
||||
// buttonsPressed->keysStates = keysDown();
|
||||
// buttonsHeld->keysStates = buttonsPressed->keysStates;
|
||||
|
||||
// #elif defined(MultiSpacc_Target_NES)
|
||||
// buttonsPressed->keysStates = pad_trigger(pad);
|
||||
// buttonsHeld->keysStates = pad_state(pad);
|
||||
|
||||
// #endif
|
||||
// }
|
||||
|
||||
// bool MultiSpacc_CheckButtonState( int button, MultiSpacc_KeysStates *buttonsStates )
|
||||
// {
|
||||
// #if defined(MultiSpacc_Target_SDLCommon)
|
||||
// return buttonsStates->keysStates[button];
|
||||
// #elif defined(MultiSpacc_Target_NDS) || defined(MultiSpacc_Target_NES)
|
||||
// return ( buttonsStates->keysStates & button );
|
||||
// #endif
|
||||
// }
|
||||
|
||||
void MultiSpacc_PollButtons( char pad, MultiSpacc_KeysStates *keysStates )
|
||||
{
|
||||
#if defined(MultiSpacc_Target_SDLCommon)
|
||||
int numkeys;
|
||||
#if defined(MultiSpacc_Target_Switch) // WIP
|
||||
keysStates->keysHeld = SDL_JoystickOpen(pad);
|
||||
|
||||
SDL_PumpEvents();
|
||||
#else
|
||||
int numkeys;
|
||||
|
||||
SDL_PumpEvents();
|
||||
|
||||
#if defined(MultiSpacc_Target_SDL12)
|
||||
keysStates->keysHeld = SDL_GetKeyState(&numkeys);
|
||||
#elif defined(MultiSpacc_Target_SDL20)
|
||||
keysStates->keysHeld = SDL_GetKeyboardState(&numkeys);
|
||||
#endif
|
||||
|
||||
if( keysStates->keysPressed == NULL )
|
||||
{
|
||||
keysStates->keysPressed = malloc( numkeys*sizeof(int) );
|
||||
memset( (void*)keysStates->keysPressed, false, numkeys*sizeof(int) );
|
||||
}
|
||||
|
||||
#if defined(MultiSpacc_Target_SDL12)
|
||||
keysStates->keysHeld = SDL_GetKeyState(&numkeys);
|
||||
#elif defined(MultiSpacc_Target_SDL20)
|
||||
keysStates->keysHeld = SDL_GetKeyboardState(&numkeys);
|
||||
#endif
|
||||
|
||||
if( keysStates->keysPressed == NULL )
|
||||
{
|
||||
keysStates->keysPressed = malloc( numkeys*sizeof(int) );
|
||||
memset( (void*)keysStates->keysPressed, false, numkeys*sizeof(int) );
|
||||
}
|
||||
|
||||
#elif defined(MultiSpacc_Target_NDS)
|
||||
scanKeys();
|
||||
keysStates->keysPressed = keysDown();
|
||||
keysStates->keysPressed = keysDown(); //keysHeld();
|
||||
keysStates->keysHeld = keysStates->keysPressed;
|
||||
|
||||
#elif defined(MultiSpacc_Target_NES)
|
||||
|
@ -67,16 +40,20 @@ void MultiSpacc_PollButtons( char pad, MultiSpacc_KeysStates *keysStates )
|
|||
bool MultiSpacc_CheckKeyPress( int key, MultiSpacc_KeysStates *keysStates )
|
||||
{
|
||||
#if defined(MultiSpacc_Target_SDLCommon)
|
||||
if ( keysStates->keysHeld[key] && !keysStates->keysPressed[key] )
|
||||
{
|
||||
keysStates->keysPressed[key] = true;
|
||||
return true;
|
||||
}
|
||||
else if ( !keysStates->keysHeld[key] && keysStates->keysPressed[key] )
|
||||
{
|
||||
keysStates->keysPressed[key] = false;
|
||||
}
|
||||
return false;
|
||||
#if defined(MultiSpacc_Target_Switch) // WIP
|
||||
return SDL_JoystickGetButton( keysStates->keysHeld, key );
|
||||
#else
|
||||
if ( keysStates->keysHeld[key] && !keysStates->keysPressed[key] )
|
||||
{
|
||||
keysStates->keysPressed[key] = true;
|
||||
return true;
|
||||
}
|
||||
else if ( !keysStates->keysHeld[key] && keysStates->keysPressed[key] )
|
||||
{
|
||||
keysStates->keysPressed[key] = false;
|
||||
}
|
||||
return false;
|
||||
#endif
|
||||
#elif defined(MultiSpacc_Target_NDS) || defined(MultiSpacc_Target_NES)
|
||||
return ( keysStates->keysPressed & key );
|
||||
#endif
|
||||
|
@ -85,7 +62,11 @@ bool MultiSpacc_CheckKeyPress( int key, MultiSpacc_KeysStates *keysStates )
|
|||
bool MultiSpacc_CheckKeyHold( int key, MultiSpacc_KeysStates *keysStates )
|
||||
{
|
||||
#if defined(MultiSpacc_Target_SDLCommon)
|
||||
return keysStates->keysHeld[key];
|
||||
#if defined(MultiSpacc_Target_Switch)
|
||||
return SDL_JoystickGetButton( keysStates->keysHeld, key );
|
||||
#else
|
||||
return keysStates->keysHeld[key];
|
||||
#endif
|
||||
#elif defined(MultiSpacc_Target_NDS) || defined(MultiSpacc_Target_NES)
|
||||
return ( keysStates->keysHeld & key );
|
||||
#endif
|
||||
|
|
|
@ -7,6 +7,7 @@ extern "C" {
|
|||
|
||||
#if defined(MultiSpacc_Target_SDL12)
|
||||
#define MultiSpacc_SDLK_ESCAPE SDLK_ESCAPE
|
||||
#define MultiSpacc_SDLK_RETURN SDLK_RETURN
|
||||
#define MultiSpacc_SDLK_TAB SDLK_TAB
|
||||
#define MultiSpacc_SDLK_UP SDLK_UP
|
||||
#define MultiSpacc_SDLK_DOWN SDLK_DOWN
|
||||
|
@ -14,6 +15,7 @@ extern "C" {
|
|||
#define MultiSpacc_SDLK_RIGHT SDLK_RIGHT
|
||||
#elif defined(MultiSpacc_Target_SDL20)
|
||||
#define MultiSpacc_SDLK_ESCAPE SDL_SCANCODE_ESCAPE
|
||||
#define MultiSpacc_SDLK_RETURN SDL_SCANCODE_RETURN
|
||||
#define MultiSpacc_SDLK_TAB SDL_SCANCODE_TAB
|
||||
#define MultiSpacc_SDLK_UP SDL_SCANCODE_UP
|
||||
#define MultiSpacc_SDLK_DOWN SDL_SCANCODE_DOWN
|
||||
|
@ -45,7 +47,9 @@ extern "C" {
|
|||
#endif
|
||||
|
||||
// Confirm
|
||||
#if defined(MultiSpacc_Target_NES)
|
||||
#if defined(MultiSpacc_Target_SDLCommon) && (defined(MultiSpacc_Target_PC) || defined(MultiSpacc_Target_Web))
|
||||
#define MultiSpacc_Key_Confirm MultiSpacc_SDLK_RETURN
|
||||
#elif defined(MultiSpacc_Target_NES)
|
||||
#define MultiSpacc_Key_Confirm PAD_A
|
||||
#endif
|
||||
|
||||
|
@ -86,7 +90,10 @@ extern "C" {
|
|||
#define MultiSpacc_Key_Left MultiSpacc_SDLK_LEFT
|
||||
#define MultiSpacc_Key_Right MultiSpacc_SDLK_RIGHT
|
||||
#elif defined(MultiSpacc_Target_NDS)
|
||||
// ...
|
||||
#define MultiSpacc_Key_Up KEY_UP
|
||||
#define MultiSpacc_Key_Down KEY_DOWN
|
||||
#define MultiSpacc_Key_Left KEY_LEFT
|
||||
#define MultiSpacc_Key_Right KEY_RIGHT
|
||||
#elif defined(MultiSpacc_Target_NES)
|
||||
#define MultiSpacc_Key_Up PAD_UP
|
||||
#define MultiSpacc_Key_Down PAD_DOWN
|
||||
|
@ -97,33 +104,22 @@ extern "C" {
|
|||
#if defined(MultiSpacc_Target_SDLCommon) && (defined(MultiSpacc_Target_PC) || defined(MultiSpacc_Target_Web))
|
||||
// #define MultiSpacc_Key_Action1 SPACE
|
||||
// #define MultiSpacc_Key_Action2 SHIFT
|
||||
// #define MultiSpacc_Key_Confirm ENTER
|
||||
// #define MultiSpacc_Key_Cancel ESC
|
||||
#endif
|
||||
|
||||
// typedef struct MultiSpacc_KeysStates {
|
||||
// #if defined(MultiSpacc_Target_SDLCommon)
|
||||
// const Uint8 *keysStates;
|
||||
// #elif defined(MultiSpacc_Target_NDS)
|
||||
// int keysStates;
|
||||
// #elif defined(MultiSpacc_Target_NES)
|
||||
// char keysStates;
|
||||
// #endif
|
||||
// } MultiSpacc_KeysStates;
|
||||
|
||||
typedef struct MultiSpacc_KeysStates {
|
||||
#if defined(MultiSpacc_Target_SDLCommon)
|
||||
Uint8 *keysPressed;
|
||||
const Uint8 *keysHeld;
|
||||
#elif defined(MultiSpacc_Target_NDS)
|
||||
int keysPressed;
|
||||
int keysHeld;
|
||||
#elif defined(MultiSpacc_Target_NES)
|
||||
char keysPressed;
|
||||
char keysHeld;
|
||||
#endif
|
||||
} MultiSpacc_KeysStates;
|
||||
|
||||
//void MultiSpacc_PollButtons( char pad, MultiSpacc_KeysStates *buttonsPressed, MultiSpacc_KeysStates *buttonsHeld );
|
||||
//bool MultiSpacc_CheckButtonState( int button, MultiSpacc_KeysStates *buttonsStates );
|
||||
void MultiSpacc_PollButtons( char pad, MultiSpacc_KeysStates *keysStates );
|
||||
bool MultiSpacc_CheckKeyPress( int key, MultiSpacc_KeysStates *keysStates );
|
||||
bool MultiSpacc_CheckKeyHold( int key, MultiSpacc_KeysStates *keysStates );
|
||||
|
|
|
@ -1,5 +1,13 @@
|
|||
#include "./MultiSpacc.h"
|
||||
|
||||
bool MultiSpacc_InitSystem(void)
|
||||
{
|
||||
#if defined(MultiSpacc_Target_SDLCommon)
|
||||
SDL_Init(SDL_INIT_EVERYTHING);
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
MultiSpacc_Surface *MultiSpacc_GetWindowSurface( MultiSpacc_Window *Window )
|
||||
{
|
||||
#if defined(MultiSpacc_Target_SDL12)
|
||||
|
|
|
@ -45,7 +45,6 @@ extern "C" {
|
|||
#endif
|
||||
|
||||
#ifdef MultiSpacc_Target_SDLCommon
|
||||
#define MultiSpacc_Init SDL_Init
|
||||
#define MultiSpacc_Surface SDL_Surface
|
||||
#define MultiSpacc_GetTicks SDL_GetTicks
|
||||
#endif
|
||||
|
@ -137,7 +136,13 @@ typedef struct MultiSpacc_MainLoopHandlerArgs {
|
|||
#define MultiSpacc_StaticScreenSizeNull true
|
||||
#endif
|
||||
|
||||
bool MultiSpacc_MainLoopHandler( MultiSpacc_MainLoopHandlerArgs *handlerArgs );
|
||||
#if defined(MultiSpacc_Target_NES)
|
||||
#define MultiSpacc_SystemClockAvailable false
|
||||
#else
|
||||
#define MultiSpacc_SystemClockAvailable true
|
||||
#endif
|
||||
|
||||
bool MultiSpacc_InitSystem(void);
|
||||
|
||||
MultiSpacc_Window *MultiSpacc_SetWindow( MultiSpacc_SurfaceConfig *windowConfig );
|
||||
MultiSpacc_Surface *MultiSpacc_GetWindowSurface( MultiSpacc_Window *Window );
|
||||
|
@ -146,6 +151,7 @@ void MultiSpacc_SetAppTitle( MultiSpacc_Window *Window, const char Title[] );
|
|||
void MultiSpacc_SetAppIcon( MultiSpacc_Window *Window, MultiSpacc_Surface *Icon );
|
||||
|
||||
bool MultiSpacc_SetMainLoop( bool functionFixedUpdate( void *args ), bool functionRealUpdate( void *args, double deltaTime ), void *args );
|
||||
bool MultiSpacc_MainLoopHandler( MultiSpacc_MainLoopHandlerArgs *handlerArgs );
|
||||
|
||||
MultiSpacc_Surface *MultiSpacc_LoadImage( char FilePath[], MultiSpacc_Surface *Screen, Uint32 *ColorKey );
|
||||
int MultiSpacc_SetColorKey( MultiSpacc_Surface *Surface, bool Flag, Uint32 Key );
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
#!/bin/sh
|
||||
#!/bin/bash
|
||||
|
||||
#[ "$(whoami)" != root ] && {
|
||||
# echo "This script must run as root".
|
||||
echo "This script must probably run as root".
|
||||
# exit -1
|
||||
#}
|
||||
|
||||
|
@ -35,4 +35,4 @@ export DEVKITARM=/opt/devkitpro/devkitARM
|
|||
export DEVKITPPC=/opt/devkitpro/devkitPPC
|
||||
[EOF]
|
||||
|
||||
. .env
|
||||
source .env
|
||||
|
|
Loading…
Reference in New Issue