├── .github └── workflows │ ├── deployment-aws.yml │ └── deployment-gcp.yml ├── README.md ├── slick_slides ├── .flutter-plugins ├── .flutter-plugins-dependencies ├── .gitignore ├── CHANGELOG.md ├── LICENSE ├── README.md ├── analysis_options.yaml ├── example │ ├── .gitignore │ ├── .metadata │ ├── README.md │ ├── analysis_options.yaml │ ├── assets │ │ ├── logo-background.jpg │ │ ├── portrait.jpg │ │ └── serverpod-avatars.webp │ ├── lib │ │ └── main.dart │ ├── pubspec.lock │ ├── pubspec.yaml │ ├── test │ │ └── widget_test.dart │ └── web │ │ ├── favicon.png │ │ ├── icons │ │ ├── Icon-192.png │ │ ├── Icon-512.png │ │ ├── Icon-maskable-192.png │ │ └── Icon-maskable-512.png │ │ ├── index.html │ │ └── manifest.json ├── lib │ ├── fonts │ │ ├── OFL-inter.txt │ │ ├── OFL-jetbrainsmono.txt │ │ ├── inter.ttf │ │ └── jetbrainsmono.ttf │ ├── slick_slides.dart │ └── src │ │ ├── deck │ │ ├── deck.dart │ │ ├── deck_controls.dart │ │ ├── slide_config.dart │ │ └── theme.dart │ │ ├── extensions │ │ └── text_span.dart │ │ ├── layouts │ │ ├── content.dart │ │ ├── person.dart │ │ ├── title.dart │ │ └── video.dart │ │ ├── slides │ │ ├── animated_code.dart │ │ ├── bullets.dart │ │ ├── full_screen_image.dart │ │ ├── person.dart │ │ ├── title.dart │ │ └── video.dart │ │ ├── transitions │ │ ├── fade.dart │ │ └── transition.dart │ │ └── widgets │ │ ├── bullets.dart │ │ ├── colored_code.dart │ │ └── gradient_text.dart ├── misc │ └── cover.jpg └── pubspec.yaml ├── slick_slides_client ├── .gitignore ├── CHANGELOG.md ├── README.md ├── analysis_options.yaml ├── dartdoc_options.yaml ├── doc │ └── endpoint.md ├── lib │ ├── slick_slides_client.dart │ └── src │ │ └── protocol │ │ ├── client.dart │ │ ├── example.dart │ │ └── protocol.dart └── pubspec.yaml └── slick_slides_server ├── .gcloudignore ├── .gitignore ├── CHANGELOG.md ├── Dockerfile ├── README.md ├── analysis_options.yaml ├── bin └── main.dart ├── config ├── development.yaml ├── generator.yaml ├── production.yaml └── staging.yaml ├── deploy ├── aws │ ├── scripts │ │ ├── appspec.yml │ │ ├── install_dependencies │ │ ├── run_serverpod │ │ └── start_server │ └── terraform │ │ ├── .gitignore │ │ ├── balancers-staging.tf │ │ ├── balancers.tf │ │ ├── cloudfront-web-staging.tf │ │ ├── cloudfront-web.tf │ │ ├── code-deploy.tf │ │ ├── config.auto.tfvars │ │ ├── database.tf │ │ ├── init-script.sh │ │ ├── instances.tf │ │ ├── main.tf │ │ ├── redis.tf │ │ ├── staging.tf │ │ ├── storage.tf │ │ ├── variables.tf │ │ └── vpc.tf └── gcp │ ├── console_gcr │ └── cloud-run-deploy.sh │ └── terraform_gce │ ├── .gitignore │ ├── config.auto.tfvars │ ├── main.tf │ └── variables.tf ├── docker-compose.yaml ├── generated ├── protocol.yaml ├── tables-serverpod.pgsql └── tables.pgsql ├── lib ├── server.dart └── src │ ├── endpoints │ └── example_endpoint.dart │ ├── future_calls │ └── example_future_call.dart │ ├── generated │ ├── endpoints.dart │ ├── example.dart │ └── protocol.dart │ ├── protocol │ └── example.yaml │ └── web │ ├── routes │ └── root.dart │ └── widgets │ └── default_page_widget.dart ├── migrations └── serverpod │ ├── 20230522155355 │ ├── definition.json │ ├── definition.sql │ ├── migration.json │ └── migration.sql │ └── 20230529140912 │ ├── definition.json │ ├── definition.sql │ ├── migration.json │ └── migration.sql ├── pubspec.lock ├── pubspec.yaml └── web ├── static ├── css │ └── style.css └── images │ ├── background.svg │ └── serverpod-logo.svg └── templates └── default.html /.github/workflows/deployment-aws.yml: -------------------------------------------------------------------------------- 1 | name: Deploy to AWS 2 | on: 3 | push: 4 | branches: [ deployment-aws-production, deployment-aws-staging ] 5 | workflow_dispatch: 6 | inputs: 7 | target: 8 | description: 'Target' 9 | required: true 10 | default: 'production' 11 | type: choice 12 | options: 13 | - 'staging' 14 | - 'production' 15 | jobs: 16 | deploy: 17 | name: Deploy to AWS 18 | runs-on: ubuntu-latest 19 | 20 | steps: 21 | - name: Checkout 22 | uses: actions/checkout@v2 23 | with: 24 | submodules: recursive 25 | 26 | - name: Setup Dart SDK 27 | uses: dart-lang/setup-dart@v1.3 28 | with: 29 | sdk: 2.18.1 30 | 31 | - name: Configure AWS credentials 32 | uses: aws-actions/configure-aws-credentials@v1 33 | with: 34 | aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }} 35 | aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }} 36 | aws-region: us-west-2 37 | 38 | - name: Create passwords file 39 | working-directory: slick_slides_server 40 | shell: bash 41 | env: 42 | SERVERPOD_PASSWORDS: ${{ secrets.SERVERPOD_PASSWORDS }} 43 | run: | 44 | pwd 45 | echo "$SERVERPOD_PASSWORDS" > config/passwords.yaml 46 | ls config/ 47 | 48 | - name: Get Dart packages 49 | working-directory: slick_slides_server 50 | run: dart pub get 51 | 52 | - name: Compile server 53 | working-directory: slick_slides_server 54 | run: dart compile kernel bin/main.dart 55 | 56 | - name: Create CodeDeploy Deployment 57 | id: deploy 58 | env: 59 | PROJECT_NAME: slick_slides 60 | AWS_NAME: slick-slides 61 | DEPLOYMENT_BUCKET: slick-slides-deployment-1661523 62 | TARGET: ${{ github.event.inputs.target }} 63 | run: | 64 | # Deploy server to AWS 65 | TARGET="${TARGET:=${GITHUB_REF##*-}}" 66 | echo "Deploying to target: $TARGET" 67 | mkdir -p vendor 68 | cp "${PROJECT_NAME}_server/deploy/aws/scripts/appspec.yml" appspec.yml 69 | zip -r deployment.zip . 70 | aws s3 cp deployment.zip "s3://${DEPLOYMENT_BUCKET}/deployment.zip" 71 | aws deploy create-deployment \ 72 | --application-name "${AWS_NAME}-app" \ 73 | --deployment-group-name "${AWS_NAME}-${TARGET}-group" \ 74 | --deployment-config-name CodeDeployDefault.OneAtATime \ 75 | --s3-location "bucket=${DEPLOYMENT_BUCKET},key=deployment.zip,bundleType=zip" 76 | -------------------------------------------------------------------------------- /.github/workflows/deployment-gcp.yml: -------------------------------------------------------------------------------- 1 | name: Deploy to GCP 2 | on: 3 | push: 4 | branches: [ deployment-gcp-production, deployment-gcp-staging ] 5 | workflow_dispatch: 6 | inputs: 7 | target: 8 | description: 'Target' 9 | required: true 10 | default: 'production' 11 | type: choice 12 | options: 13 | - 'staging' 14 | - 'production' 15 | 16 | env: 17 | # TODO: Update with your Google Cloud project id. If you have changed the 18 | # region and zone in your Terraform configuration, you will need to change 19 | # it here too. 20 | PROJECT: "" 21 | REGION: us-central1 22 | ZONE: us-central1-c 23 | 24 | jobs: 25 | deploy: 26 | name: Deploy to Google Cloud Run 27 | runs-on: ubuntu-latest 28 | 29 | steps: 30 | - name: Checkout 31 | uses: actions/checkout@v3 32 | with: 33 | submodules: recursive 34 | 35 | - name: Setting Target Mode from Input 36 | if: ${{ github.event.inputs.target != '' }} 37 | run: echo "TARGET=${{ github.event.inputs.target }}" >> $GITHUB_ENV 38 | 39 | - name: Setting Target mode based on branch 40 | if: ${{ github.event.inputs.target == '' }} 41 | run: echo "TARGET=${GITHUB_REF##*-}" >> $GITHUB_ENV 42 | 43 | - name: Set repository 44 | run: echo "REPOSITORY=serverpod-${{ env.TARGET }}-container" >> $GITHUB_ENV 45 | 46 | - name: Set Image Name 47 | run: echo "IMAGE_NAME=serverpod" >> $GITHUB_ENV 48 | 49 | - name: Set Service Name 50 | run: echo "SERVICE_NAME=$(echo $IMAGE_NAME | sed 's/[^a-zA-Z0-9]/-/g')" >> $GITHUB_ENV 51 | 52 | - name: Test 53 | run: echo $SERVICE_NAME 54 | 55 | 56 | - id: "auth" 57 | name: "Authenticate to Google Cloud" 58 | uses: "google-github-actions/auth@v1" 59 | with: 60 | credentials_json: "${{ secrets.GOOGLE_CREDENTIALS }}" 61 | 62 | - name: Create passwords file 63 | working-directory: slick_slides_server 64 | shell: bash 65 | env: 66 | SERVERPOD_PASSWORDS: ${{ secrets.SERVERPOD_PASSWORDS }} 67 | run: | 68 | pwd 69 | echo "$SERVERPOD_PASSWORDS" > config/passwords.yaml 70 | ls config/ 71 | 72 | - name: Configure Docker 73 | working-directory: slick_slides_server 74 | run: gcloud auth configure-docker ${{ env.REGION }}-docker.pkg.dev 75 | 76 | - name: Build the Docker image 77 | working-directory: slick_slides_server 78 | run: "docker build -t $IMAGE_NAME ." 79 | 80 | - name: Tag the Docker image 81 | working-directory: slick_slides_server 82 | run: docker tag $IMAGE_NAME ${{ env.REGION }}-docker.pkg.dev/${{ env.PROJECT }}/${{ env.REPOSITORY }}/$IMAGE_NAME 83 | 84 | - name: Push Docker image 85 | working-directory: slick_slides_server 86 | run: docker push ${{ env.REGION }}-docker.pkg.dev/${{ env.PROJECT }}/${{ env.REPOSITORY }}/$IMAGE_NAME 87 | 88 | # Uncomment the following code to automatically restart the servers in the 89 | # instance group when you push a new version of your code. Before doing 90 | # this, make sure that you have successfully deployed a first version. 91 | # 92 | # - name: Restart servers in instance group 93 | # run: | 94 | # gcloud compute instance-groups managed rolling-action replace serverpod-${{ env.TARGET }}-group \ 95 | # --project=${{ env.PROJECT }} \ 96 | # --replacement-method='substitute' \ 97 | # --max-surge=1 \ 98 | # --max-unavailable=1 \ 99 | # --zone=${{ env.ZONE }} 100 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Slick Slides 2 | 3 | ![Slick Slides Cover](https://raw.githubusercontent.com/serverpod/slick_slides/main/slick_slides/misc/cover.jpg) 4 | 5 | You are probably looking for the main dart package [here](https://github.com/serverpod/slick_slides/tree/main/slick_slides). -------------------------------------------------------------------------------- /slick_slides/.flutter-plugins: -------------------------------------------------------------------------------- 1 | # This is a generated file; do not edit or check into version control. 2 | audioplayers=/Users/viktor/.pub-cache/hosted/pub.dev/audioplayers-5.2.1/ 3 | audioplayers_android=/Users/viktor/.pub-cache/hosted/pub.dev/audioplayers_android-4.0.3/ 4 | audioplayers_darwin=/Users/viktor/.pub-cache/hosted/pub.dev/audioplayers_darwin-5.0.2/ 5 | audioplayers_linux=/Users/viktor/.pub-cache/hosted/pub.dev/audioplayers_linux-3.1.0/ 6 | audioplayers_web=/Users/viktor/.pub-cache/hosted/pub.dev/audioplayers_web-4.1.0/ 7 | audioplayers_windows=/Users/viktor/.pub-cache/hosted/pub.dev/audioplayers_windows-3.1.0/ 8 | path_provider=/Users/viktor/.pub-cache/hosted/pub.dev/path_provider-2.1.2/ 9 | path_provider_android=/Users/viktor/.pub-cache/hosted/pub.dev/path_provider_android-2.2.2/ 10 | path_provider_foundation=/Users/viktor/.pub-cache/hosted/pub.dev/path_provider_foundation-2.3.2/ 11 | path_provider_linux=/Users/viktor/.pub-cache/hosted/pub.dev/path_provider_linux-2.2.1/ 12 | path_provider_windows=/Users/viktor/.pub-cache/hosted/pub.dev/path_provider_windows-2.2.1/ 13 | video_player=/Users/viktor/.pub-cache/hosted/pub.dev/video_player-2.8.3/ 14 | video_player_android=/Users/viktor/.pub-cache/hosted/pub.dev/video_player_android-2.4.12/ 15 | video_player_avfoundation=/Users/viktor/.pub-cache/hosted/pub.dev/video_player_avfoundation-2.5.6/ 16 | video_player_web=/Users/viktor/.pub-cache/hosted/pub.dev/video_player_web-2.3.0/ 17 | -------------------------------------------------------------------------------- /slick_slides/.flutter-plugins-dependencies: -------------------------------------------------------------------------------- 1 | {"info":"This is a generated file; do not edit or check into version control.","plugins":{"ios":[{"name":"audioplayers_darwin","path":"/Users/viktor/.pub-cache/hosted/pub.dev/audioplayers_darwin-5.0.2/","native_build":true,"dependencies":[]},{"name":"path_provider_foundation","path":"/Users/viktor/.pub-cache/hosted/pub.dev/path_provider_foundation-2.3.2/","shared_darwin_source":true,"native_build":true,"dependencies":[]},{"name":"video_player_avfoundation","path":"/Users/viktor/.pub-cache/hosted/pub.dev/video_player_avfoundation-2.5.6/","shared_darwin_source":true,"native_build":true,"dependencies":[]}],"android":[{"name":"audioplayers_android","path":"/Users/viktor/.pub-cache/hosted/pub.dev/audioplayers_android-4.0.3/","native_build":true,"dependencies":[]},{"name":"path_provider_android","path":"/Users/viktor/.pub-cache/hosted/pub.dev/path_provider_android-2.2.2/","native_build":true,"dependencies":[]},{"name":"video_player_android","path":"/Users/viktor/.pub-cache/hosted/pub.dev/video_player_android-2.4.12/","native_build":true,"dependencies":[]}],"macos":[{"name":"audioplayers_darwin","path":"/Users/viktor/.pub-cache/hosted/pub.dev/audioplayers_darwin-5.0.2/","native_build":true,"dependencies":[]},{"name":"path_provider_foundation","path":"/Users/viktor/.pub-cache/hosted/pub.dev/path_provider_foundation-2.3.2/","shared_darwin_source":true,"native_build":true,"dependencies":[]},{"name":"video_player_avfoundation","path":"/Users/viktor/.pub-cache/hosted/pub.dev/video_player_avfoundation-2.5.6/","shared_darwin_source":true,"native_build":true,"dependencies":[]}],"linux":[{"name":"audioplayers_linux","path":"/Users/viktor/.pub-cache/hosted/pub.dev/audioplayers_linux-3.1.0/","native_build":true,"dependencies":[]},{"name":"path_provider_linux","path":"/Users/viktor/.pub-cache/hosted/pub.dev/path_provider_linux-2.2.1/","native_build":false,"dependencies":[]}],"windows":[{"name":"audioplayers_windows","path":"/Users/viktor/.pub-cache/hosted/pub.dev/audioplayers_windows-3.1.0/","native_build":true,"dependencies":[]},{"name":"path_provider_windows","path":"/Users/viktor/.pub-cache/hosted/pub.dev/path_provider_windows-2.2.1/","native_build":false,"dependencies":[]}],"web":[{"name":"audioplayers_web","path":"/Users/viktor/.pub-cache/hosted/pub.dev/audioplayers_web-4.1.0/","dependencies":[]},{"name":"video_player_web","path":"/Users/viktor/.pub-cache/hosted/pub.dev/video_player_web-2.3.0/","dependencies":[]}]},"dependencyGraph":[{"name":"audioplayers","dependencies":["audioplayers_android","audioplayers_darwin","audioplayers_linux","audioplayers_web","audioplayers_windows","path_provider"]},{"name":"audioplayers_android","dependencies":[]},{"name":"audioplayers_darwin","dependencies":[]},{"name":"audioplayers_linux","dependencies":[]},{"name":"audioplayers_web","dependencies":[]},{"name":"audioplayers_windows","dependencies":[]},{"name":"path_provider","dependencies":["path_provider_android","path_provider_foundation","path_provider_linux","path_provider_windows"]},{"name":"path_provider_android","dependencies":[]},{"name":"path_provider_foundation","dependencies":[]},{"name":"path_provider_linux","dependencies":[]},{"name":"path_provider_windows","dependencies":[]},{"name":"video_player","dependencies":["video_player_android","video_player_avfoundation","video_player_web"]},{"name":"video_player_android","dependencies":[]},{"name":"video_player_avfoundation","dependencies":[]},{"name":"video_player_web","dependencies":[]}],"date_created":"2024-04-02 15:43:00.855487","version":"3.19.4"} -------------------------------------------------------------------------------- /slick_slides/.gitignore: -------------------------------------------------------------------------------- 1 | # Miscellaneous 2 | *.class 3 | *.log 4 | *.pyc 5 | *.swp 6 | .DS_Store 7 | .atom/ 8 | .buildlog/ 9 | .history 10 | .svn/ 11 | migrate_working_dir/ 12 | 13 | # IntelliJ related 14 | *.iml 15 | *.ipr 16 | *.iws 17 | .idea/ 18 | 19 | # The .vscode folder contains launch configuration and tasks you configure in 20 | # VS Code which you may wish to be included in version control, so this line 21 | # is commented out by default. 22 | #.vscode/ 23 | 24 | # Flutter/Dart/Pub related 25 | # Libraries should not include pubspec.lock, per https://dart.dev/guides/libraries/private-files#pubspeclock. 26 | /pubspec.lock 27 | **/doc/api/ 28 | .dart_tool/ 29 | .packages 30 | build/ 31 | -------------------------------------------------------------------------------- /slick_slides/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | ## 0.2.1 2 | 3 | * Adds presenter view. 4 | 5 | ## 0.2.0 6 | 7 | * Improved example. 8 | * Support for playing an audio file when showing a slide. 9 | * Correctly caches images on bullet slides. 10 | * Support for video slides. 11 | * Updates syntax coloring package. 12 | * Fixes spacing between title and subtitle in default themes. 13 | * Updates to latest Flutter version. 14 | 15 | ## 0.1.0 16 | 17 | * Beta release. Pretty much feature complete. 18 | 19 | ## 0.0.1 20 | 21 | * Initial release. 22 | -------------------------------------------------------------------------------- /slick_slides/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright 2023 The Serverpod authors 2 | 3 | Redistribution and use in source and binary forms, with or without modification, are permitted provided that the 4 | following conditions are met: 5 | 6 | 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following 7 | disclaimer. 8 | 9 | 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following 10 | disclaimer in the documentation and/or other materials provided with the distribution. 11 | 12 | 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products 13 | derived from this software without specific prior written permission. 14 | 15 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, 16 | INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 17 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 18 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 19 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 20 | WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 21 | THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 22 | -------------------------------------------------------------------------------- /slick_slides/README.md: -------------------------------------------------------------------------------- 1 | # Slick Slides 2 | 3 | ![Slick Slides Cover](https://raw.githubusercontent.com/serverpod/slick_slides/main/slick_slides/misc/cover.jpg) 4 | 5 | Use this package to create slick presentations for your tech talk and presentations. It's great for beautifully formatting and animating code but also has support for title slides, images, or any other Flutter Widgets. 6 | 7 | Slick Slides is created and maintained by the [Serverpod](https://serverpod.dev) team. Serverpod is a server written in Dart for the Flutter community, check it out if you haven't. 8 | 9 | ## Getting started 10 | It's quick to setup Slick Slides. Just add the `slick_slides` package to your `pubspec.yaml` file, then follow the guide below. 11 | 12 | ### Include fonts 13 | By default, Slick Slides uses _Inter_ and _Jetbrains Mono_ to display text and code. You will need to add them to your pubspec to make them accessible to the Slick Slides package. This is an example of what your `flutter` section in the `pubspec.yaml` file can look like with the fonts included. The fonts will be loaded to the package, so there is nothing more you need to do other than add the font references to your pubspec file. 14 | 15 | ```yaml 16 | flutter: 17 | uses-material-design: true 18 | 19 | # Include fonts from slick_slides package. 20 | fonts: 21 | - family: Inter 22 | fonts: 23 | - asset: packages/slick_slides/fonts/inter.ttf 24 | - family: JetbrainsMono 25 | fonts: 26 | - asset: packages/slick_slides/fonts/jetbrainsmono.ttf 27 | 28 | # Include all assets from the assets directory. 29 | assets: 30 | - assets/ 31 | ``` 32 | 33 | ### Flutter code setup 34 | Before using Slick Slides, you need to initialize it. This loads code formaters and any other required resources. If you initialize Slick Slides before you call `runApp`, you will need to call `WidgetsFlutterBinding.ensureInitialized()` before you call the `initialize` method. 35 | 36 | ```dart 37 | WidgetsFlutterBinding.ensureInitialized(); 38 | await SlickSlides.initialize(); 39 | ``` 40 | 41 | Now, you can add the `SlideDeck` widget anywhere in your widget tree, but for the normal use case, you use it as the home of your `MaterialApp`. The `SlideDeck` maintains its own navigator and theme for the slides. 42 | 43 | To build your presentation, pass a number of `Slide` objects to the `SlideDeck` widget. The `Slide` objects contain builder methods for the slides, theme data, information about transitions, and other properties. There are a number of pre-made slides that you can very easily drop into your presentation, e.g., `TitleSlide`, `BulletsSlide`, `AnimatedCodeSlide`, and `PersonSlide`, but you can also create custom slides with any type of layout and content. 44 | 45 | This is an example of a simple `SlideDeck` with two slides: 46 | 47 | ```dart 48 | // Setup a default transition. 49 | const _defaultTransition = SlickFadeTransition( 50 | color: Colors.black, 51 | ); 52 | 53 | class MyHomePage extends StatelessWidget { 54 | const MyHomePage({ 55 | super.key, 56 | }); 57 | 58 | @override 59 | Widget build(BuildContext context) { 60 | // Create a new SlideDeck with a TitleSlide and a BulletsSlide. 61 | return SlideDeck( 62 | slides: [ 63 | TitleSlide( 64 | title: 'Slick Slides', 65 | subtitle: 'Stunning presentations in Flutter', 66 | transition: _defaultTransition, 67 | ), 68 | BulletsSlide( 69 | title: 'What is Slick Slides?', 70 | bulletByBullet: true, 71 | bullets: const [ 72 | 'Bullet number 1', 73 | 'A second bullet', 74 | ], 75 | transition: _defaultTransition, 76 | ), 77 | ], 78 | ); 79 | } 80 | } 81 | ``` 82 | 83 | ## Displaying and animating code 84 | To display or animate code, use the `AnimatedCodeSlide`. Slick Slides will do a diff between your code snippets and animate the changes in the code as if you were typing. You can also highlight lines in the code to bring extra attention to them. This is a simple example: 85 | 86 | ```dart 87 | const _codeExampleA = '''class MyClass { 88 | 89 | } 90 | '''; 91 | 92 | const _codeExampleB = '''class MyClass { 93 | String methodToAnimateIn() { 94 | return 'Hello world!'; 95 | } 96 | } 97 | '''; 98 | 99 | @override 100 | Widget build(BuildContext context) { 101 | // Create a new SlideDeck with a TitleSlide and a BulletsSlide. 102 | return SlideDeck( 103 | slides: [ 104 | AnimatedCodeSlide( 105 | formattedCode: [ 106 | FormattedCode( 107 | code: _codeExampleA, 108 | ), 109 | FormattedCode( 110 | code: _codeExampleB, 111 | highlightedLines: [1, 2, 3], 112 | ), 113 | ], 114 | ), 115 | ], 116 | ); 117 | } 118 | ``` 119 | 120 | ## Creating custom types of slides 121 | Slick Slides allows you to create custom types of slides with any Flutter widgets. You can even create interactive slides in your deck. For slides that use custom assets, such as images or animations, that need to be loaded, you can use the `onPrecache` property to provide code that loads the slide ahead of time. This is an example of a custom slide that displays an animated Serverpod logo (from the `made_with_serverpod` package): 122 | 123 | ```dart 124 | Slide( 125 | builder: (context) { 126 | return const ContentLayout( 127 | content: Center( 128 | child: SizedBox( 129 | width: 600, 130 | child: AnimatedServerpodLogo( 131 | brightness: Brightness.dark, 132 | animate: true, 133 | loop: false, 134 | ), 135 | ), 136 | ), 137 | ); 138 | }, 139 | transition: const SlickFadeTransition(), 140 | onPrecache: (context) async { 141 | AnimatedServerpodLogo.precache(); 142 | }, 143 | ) 144 | ``` 145 | 146 | Tip! You can also override the `Slide` class if you want to make more reusable types of slides. Have a look at the source code for the default set of slides to see how you do this. 147 | 148 | ## Other cool features 149 | These are some sweet things you can do with Slick Slides: 150 | 151 | - Create slides with rich text. 152 | - Do hero animations (just add heroes as you would in any Flutter transition). 153 | - Create interactive slides with custom widgets. 154 | - Add custom themes. A default dark and light theme is provided, but you can easily create and customize your own. 155 | - Autoplaying decks. 156 | - Audio files associated with slides and played when a slide is shown. 157 | 158 | ## Known issues 159 | Slick Slides works well, but there are a couple of known issues that we hope to fix in the future (conrtributions are very welcome): 160 | 161 | - The custom font for displaying highlighted code (by default Jetbrains Mono) doesn't work on Flutter web. 162 | - Hero animations gets 'stuck' if interrupted, e.g. by moving quickly to another slide when the animation is running. 163 | - Video slides does not fade out correctly when leaving a slide using a fade transition. -------------------------------------------------------------------------------- /slick_slides/analysis_options.yaml: -------------------------------------------------------------------------------- 1 | include: package:flutter_lints/flutter.yaml 2 | 3 | linter: 4 | rules: 5 | - public_member_api_docs -------------------------------------------------------------------------------- /slick_slides/example/.gitignore: -------------------------------------------------------------------------------- 1 | # Miscellaneous 2 | *.class 3 | *.log 4 | *.pyc 5 | *.swp 6 | .DS_Store 7 | .atom/ 8 | .buildlog/ 9 | .history 10 | .svn/ 11 | migrate_working_dir/ 12 | 13 | # IntelliJ related 14 | *.iml 15 | *.ipr 16 | *.iws 17 | .idea/ 18 | 19 | # The .vscode folder contains launch configuration and tasks you configure in 20 | # VS Code which you may wish to be included in version control, so this line 21 | # is commented out by default. 22 | #.vscode/ 23 | 24 | # Flutter/Dart/Pub related 25 | **/doc/api/ 26 | **/ios/Flutter/.last_build_id 27 | .dart_tool/ 28 | .flutter-plugins 29 | .flutter-plugins-dependencies 30 | .packages 31 | .pub-cache/ 32 | .pub/ 33 | /build/ 34 | /macos/ 35 | /linux/ 36 | /android/ 37 | /ios/ 38 | /windows/ 39 | 40 | # Symbolication related 41 | app.*.symbols 42 | 43 | # Obfuscation related 44 | app.*.map.json 45 | 46 | # Android Studio will place build artifacts here 47 | /android/app/debug 48 | /android/app/profile 49 | /android/app/release 50 | -------------------------------------------------------------------------------- /slick_slides/example/.metadata: -------------------------------------------------------------------------------- 1 | # This file tracks properties of this Flutter project. 2 | # Used by Flutter tool to assess capabilities and perform upgrades etc. 3 | # 4 | # This file should be version controlled. 5 | 6 | version: 7 | revision: f468f3366c26a5092eb964a230ce7892fda8f2f8 8 | channel: stable 9 | 10 | project_type: app 11 | 12 | # Tracks metadata for the flutter migrate command 13 | migration: 14 | platforms: 15 | - platform: root 16 | create_revision: f468f3366c26a5092eb964a230ce7892fda8f2f8 17 | base_revision: f468f3366c26a5092eb964a230ce7892fda8f2f8 18 | - platform: android 19 | create_revision: f468f3366c26a5092eb964a230ce7892fda8f2f8 20 | base_revision: f468f3366c26a5092eb964a230ce7892fda8f2f8 21 | - platform: ios 22 | create_revision: f468f3366c26a5092eb964a230ce7892fda8f2f8 23 | base_revision: f468f3366c26a5092eb964a230ce7892fda8f2f8 24 | - platform: linux 25 | create_revision: f468f3366c26a5092eb964a230ce7892fda8f2f8 26 | base_revision: f468f3366c26a5092eb964a230ce7892fda8f2f8 27 | - platform: macos 28 | create_revision: f468f3366c26a5092eb964a230ce7892fda8f2f8 29 | base_revision: f468f3366c26a5092eb964a230ce7892fda8f2f8 30 | - platform: web 31 | create_revision: f468f3366c26a5092eb964a230ce7892fda8f2f8 32 | base_revision: f468f3366c26a5092eb964a230ce7892fda8f2f8 33 | - platform: windows 34 | create_revision: f468f3366c26a5092eb964a230ce7892fda8f2f8 35 | base_revision: f468f3366c26a5092eb964a230ce7892fda8f2f8 36 | 37 | # User provided section 38 | 39 | # List of Local paths (relative to this file) that should be 40 | # ignored by the migrate tool. 41 | # 42 | # Files that are not part of the templates will be ignored by default. 43 | unmanaged_files: 44 | - 'lib/main.dart' 45 | - 'ios/Runner.xcodeproj/project.pbxproj' 46 | -------------------------------------------------------------------------------- /slick_slides/example/README.md: -------------------------------------------------------------------------------- 1 | # example 2 | 3 | A new Flutter project. 4 | 5 | ## Getting Started 6 | 7 | This project is a starting point for a Flutter application. 8 | 9 | A few resources to get you started if this is your first Flutter project: 10 | 11 | - [Lab: Write your first Flutter app](https://docs.flutter.dev/get-started/codelab) 12 | - [Cookbook: Useful Flutter samples](https://docs.flutter.dev/cookbook) 13 | 14 | For help getting started with Flutter development, view the 15 | [online documentation](https://docs.flutter.dev/), which offers tutorials, 16 | samples, guidance on mobile development, and a full API reference. 17 | -------------------------------------------------------------------------------- /slick_slides/example/analysis_options.yaml: -------------------------------------------------------------------------------- 1 | # This file configures the analyzer, which statically analyzes Dart code to 2 | # check for errors, warnings, and lints. 3 | # 4 | # The issues identified by the analyzer are surfaced in the UI of Dart-enabled 5 | # IDEs (https://dart.dev/tools#ides-and-editors). The analyzer can also be 6 | # invoked from the command line by running `flutter analyze`. 7 | 8 | # The following line activates a set of recommended lints for Flutter apps, 9 | # packages, and plugins designed to encourage good coding practices. 10 | include: package:flutter_lints/flutter.yaml 11 | 12 | linter: 13 | # The lint rules applied to this project can be customized in the 14 | # section below to disable rules from the `package:flutter_lints/flutter.yaml` 15 | # included above or to enable additional rules. A list of all available lints 16 | # and their documentation is published at 17 | # https://dart-lang.github.io/linter/lints/index.html. 18 | # 19 | # Instead of disabling a lint rule for the entire project in the 20 | # section below, it can also be suppressed for a single line of code 21 | # or a specific dart file by using the `// ignore: name_of_lint` and 22 | # `// ignore_for_file: name_of_lint` syntax on the line or in the file 23 | # producing the lint. 24 | rules: 25 | # avoid_print: false # Uncomment to disable the `avoid_print` rule 26 | # prefer_single_quotes: true # Uncomment to enable the `prefer_single_quotes` rule 27 | 28 | # Additional information about this file can be found at 29 | # https://dart.dev/guides/language/analysis-options 30 | -------------------------------------------------------------------------------- /slick_slides/example/assets/logo-background.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/serverpod/slick_slides/ecb9b35a41fae1536f6ebc4399bcd3995dc8c1ba/slick_slides/example/assets/logo-background.jpg -------------------------------------------------------------------------------- /slick_slides/example/assets/portrait.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/serverpod/slick_slides/ecb9b35a41fae1536f6ebc4399bcd3995dc8c1ba/slick_slides/example/assets/portrait.jpg -------------------------------------------------------------------------------- /slick_slides/example/assets/serverpod-avatars.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/serverpod/slick_slides/ecb9b35a41fae1536f6ebc4399bcd3995dc8c1ba/slick_slides/example/assets/serverpod-avatars.webp -------------------------------------------------------------------------------- /slick_slides/example/lib/main.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:made_with_serverpod/made_with_serverpod.dart'; 3 | import 'package:slick_slides/slick_slides.dart'; 4 | 5 | void main() async { 6 | WidgetsFlutterBinding.ensureInitialized(); 7 | await SlickSlides.initialize(); 8 | 9 | runApp(const MyApp()); 10 | } 11 | 12 | const _defaultTransition = SlickFadeTransition( 13 | color: Colors.black, 14 | ); 15 | 16 | const _codeExampleA = '''class MyHomePage extends StatelessWidget { 17 | const MyHomePage({super.key}); 18 | 19 | @override 20 | Widget build(BuildContext context) { 21 | 22 | } 23 | }'''; 24 | 25 | const _codeExampleB = '''class MyHomePage extends StatelessWidget { 26 | const MyHomePage({super.key}); 27 | 28 | @override 29 | Widget build(BuildContext context) { 30 | return SlideDeck( 31 | slides: [ 32 | Slide( 33 | builder: (context) { 34 | return const TitleSlide( 35 | title: Text('Slick Slides'), 36 | subtitle: Text('Stunning presentations in Flutter'), 37 | ); 38 | }, 39 | ), 40 | ], 41 | ); 42 | } 43 | }'''; 44 | 45 | class MyApp extends StatelessWidget { 46 | const MyApp({super.key}); 47 | 48 | // This widget is the root of your application. 49 | @override 50 | Widget build(BuildContext context) { 51 | return MaterialApp( 52 | title: 'Slick Slides Demo', 53 | theme: ThemeData( 54 | colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple), 55 | useMaterial3: true, 56 | ), 57 | home: const MyHomePage(), 58 | ); 59 | } 60 | } 61 | 62 | class MyHomePage extends StatelessWidget { 63 | const MyHomePage({ 64 | super.key, 65 | }); 66 | 67 | @override 68 | Widget build(BuildContext context) { 69 | return SlideDeck( 70 | slides: [ 71 | FullScreenImageSlide( 72 | image: const AssetImage('assets/logo-background.jpg'), 73 | title: 'Slick Slides', 74 | subtitle: 'Stunning presentations\nwith Flutter', 75 | alignment: const Alignment(0.6, 0.0), 76 | theme: const SlideThemeData.darkAlt(), 77 | transition: _defaultTransition, 78 | ), 79 | BulletsSlide( 80 | title: 'What is Slick Slides?', 81 | bulletByBullet: true, 82 | bullets: const [ 83 | 'Slick Slides was born out of the need to make nice looking ' 84 | 'slides for Serverpod at the FlutterCon conference.', 85 | 'It comes with many built-in slide types, and is easy to ' 86 | 'extend with your own.', 87 | 'Browse through the slides in this presentation to see ' 88 | 'what it can do.', 89 | 'If you use Slick Slides for your presentation, please ' 90 | 'give some credit to Serverpod for the work we put into ' 91 | 'this package. Also, check out Serverpod if you haven\'t ' 92 | 'already, it\'s a great way to build your backend in ' 93 | 'Dart.', 94 | ], 95 | transition: _defaultTransition, 96 | ), 97 | BulletsSlide( 98 | title: 'Bullets with images', 99 | image: const AssetImage('assets/serverpod-avatars.webp'), 100 | bullets: [ 101 | 'Add images to you presentation with a single line of code.', 102 | 'Bullet point slides can have images too.', 103 | ], 104 | transition: _defaultTransition, 105 | ), 106 | PersonSlide( 107 | title: 'Rockstar Flutter Developer', 108 | name: 'Philippa Flutterista', 109 | image: const AssetImage( 110 | 'assets/portrait.jpg', 111 | ), 112 | transition: _defaultTransition, 113 | ), 114 | Slide( 115 | builder: (context) { 116 | return const ContentLayout( 117 | content: Center( 118 | child: SizedBox( 119 | width: 600, 120 | child: AnimatedServerpodLogo( 121 | brightness: Brightness.dark, 122 | animate: true, 123 | loop: false, 124 | ), 125 | ), 126 | ), 127 | ); 128 | }, 129 | transition: const SlickFadeTransition(), 130 | onPrecache: (context) async { 131 | AnimatedServerpodLogo.precache(); 132 | }, 133 | ), 134 | BulletsSlide( 135 | theme: const SlideThemeData.light(), 136 | title: 'Themes', 137 | bullets: const [ 138 | 'Use the built in themes or create your own.', 139 | 'This is the default light theme.', 140 | ], 141 | transition: _defaultTransition, 142 | ), 143 | AnimatedCodeSlide( 144 | formattedCode: [ 145 | FormattedCode( 146 | code: _codeExampleA, 147 | ), 148 | FormattedCode( 149 | code: _codeExampleB, 150 | highlightedLines: [5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16], 151 | ), 152 | ], 153 | ), 154 | ], 155 | ); 156 | } 157 | } 158 | -------------------------------------------------------------------------------- /slick_slides/example/pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: example 2 | description: A showcase for the Slick Slides package. 3 | publish_to: 'none' # Remove this line if you wish to publish to pub.dev 4 | 5 | version: 1.0.0 6 | 7 | environment: 8 | sdk: '>=3.0.6 <4.0.0' 9 | 10 | dependencies: 11 | flutter: 12 | sdk: flutter 13 | 14 | cupertino_icons: ^1.0.2 15 | made_with_serverpod: ^1.1.0 16 | 17 | slick_slides: 18 | path: ../ 19 | 20 | dev_dependencies: 21 | flutter_test: 22 | sdk: flutter 23 | 24 | flutter_lints: ^2.0.0 25 | 26 | flutter: 27 | uses-material-design: true 28 | 29 | # Include fonts from slick_slides package. 30 | fonts: 31 | - family: Inter 32 | fonts: 33 | - asset: packages/slick_slides/fonts/inter.ttf 34 | - family: JetbrainsMono 35 | fonts: 36 | - asset: packages/slick_slides/fonts/jetbrainsmono.ttf 37 | 38 | # Include all assets from the assets directory. 39 | assets: 40 | - assets/ 41 | -------------------------------------------------------------------------------- /slick_slides/example/test/widget_test.dart: -------------------------------------------------------------------------------- 1 | // This is a basic Flutter widget test. 2 | // 3 | // To perform an interaction with a widget in your test, use the WidgetTester 4 | // utility in the flutter_test package. For example, you can send tap and scroll 5 | // gestures. You can also use WidgetTester to find child widgets in the widget 6 | // tree, read text, and verify that the values of widget properties are correct. 7 | 8 | import 'package:flutter/material.dart'; 9 | import 'package:flutter_test/flutter_test.dart'; 10 | 11 | import 'package:example/main.dart'; 12 | 13 | void main() { 14 | testWidgets('Counter increments smoke test', (WidgetTester tester) async { 15 | // Build our app and trigger a frame. 16 | await tester.pumpWidget(const MyApp()); 17 | 18 | // Verify that our counter starts at 0. 19 | expect(find.text('0'), findsOneWidget); 20 | expect(find.text('1'), findsNothing); 21 | 22 | // Tap the '+' icon and trigger a frame. 23 | await tester.tap(find.byIcon(Icons.add)); 24 | await tester.pump(); 25 | 26 | // Verify that our counter has incremented. 27 | expect(find.text('0'), findsNothing); 28 | expect(find.text('1'), findsOneWidget); 29 | }); 30 | } 31 | -------------------------------------------------------------------------------- /slick_slides/example/web/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/serverpod/slick_slides/ecb9b35a41fae1536f6ebc4399bcd3995dc8c1ba/slick_slides/example/web/favicon.png -------------------------------------------------------------------------------- /slick_slides/example/web/icons/Icon-192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/serverpod/slick_slides/ecb9b35a41fae1536f6ebc4399bcd3995dc8c1ba/slick_slides/example/web/icons/Icon-192.png -------------------------------------------------------------------------------- /slick_slides/example/web/icons/Icon-512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/serverpod/slick_slides/ecb9b35a41fae1536f6ebc4399bcd3995dc8c1ba/slick_slides/example/web/icons/Icon-512.png -------------------------------------------------------------------------------- /slick_slides/example/web/icons/Icon-maskable-192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/serverpod/slick_slides/ecb9b35a41fae1536f6ebc4399bcd3995dc8c1ba/slick_slides/example/web/icons/Icon-maskable-192.png -------------------------------------------------------------------------------- /slick_slides/example/web/icons/Icon-maskable-512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/serverpod/slick_slides/ecb9b35a41fae1536f6ebc4399bcd3995dc8c1ba/slick_slides/example/web/icons/Icon-maskable-512.png -------------------------------------------------------------------------------- /slick_slides/example/web/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | example 33 | 34 | 35 | 39 | 40 | 41 | 42 | 43 | 58 | 59 | 60 | -------------------------------------------------------------------------------- /slick_slides/example/web/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "example", 3 | "short_name": "example", 4 | "start_url": ".", 5 | "display": "standalone", 6 | "background_color": "#0175C2", 7 | "theme_color": "#0175C2", 8 | "description": "A new Flutter project.", 9 | "orientation": "portrait-primary", 10 | "prefer_related_applications": false, 11 | "icons": [ 12 | { 13 | "src": "icons/Icon-192.png", 14 | "sizes": "192x192", 15 | "type": "image/png" 16 | }, 17 | { 18 | "src": "icons/Icon-512.png", 19 | "sizes": "512x512", 20 | "type": "image/png" 21 | }, 22 | { 23 | "src": "icons/Icon-maskable-192.png", 24 | "sizes": "192x192", 25 | "type": "image/png", 26 | "purpose": "maskable" 27 | }, 28 | { 29 | "src": "icons/Icon-maskable-512.png", 30 | "sizes": "512x512", 31 | "type": "image/png", 32 | "purpose": "maskable" 33 | } 34 | ] 35 | } 36 | -------------------------------------------------------------------------------- /slick_slides/lib/fonts/OFL-inter.txt: -------------------------------------------------------------------------------- 1 | Copyright 2020 The Inter Project Authors (https://github.com/rsms/inter) 2 | 3 | This Font Software is licensed under the SIL Open Font License, Version 1.1. 4 | This license is copied below, and is also available with a FAQ at: 5 | http://scripts.sil.org/OFL 6 | 7 | 8 | ----------------------------------------------------------- 9 | SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 10 | ----------------------------------------------------------- 11 | 12 | PREAMBLE 13 | The goals of the Open Font License (OFL) are to stimulate worldwide 14 | development of collaborative font projects, to support the font creation 15 | efforts of academic and linguistic communities, and to provide a free and 16 | open framework in which fonts may be shared and improved in partnership 17 | with others. 18 | 19 | The OFL allows the licensed fonts to be used, studied, modified and 20 | redistributed freely as long as they are not sold by themselves. The 21 | fonts, including any derivative works, can be bundled, embedded, 22 | redistributed and/or sold with any software provided that any reserved 23 | names are not used by derivative works. The fonts and derivatives, 24 | however, cannot be released under any other type of license. The 25 | requirement for fonts to remain under this license does not apply 26 | to any document created using the fonts or their derivatives. 27 | 28 | DEFINITIONS 29 | "Font Software" refers to the set of files released by the Copyright 30 | Holder(s) under this license and clearly marked as such. This may 31 | include source files, build scripts and documentation. 32 | 33 | "Reserved Font Name" refers to any names specified as such after the 34 | copyright statement(s). 35 | 36 | "Original Version" refers to the collection of Font Software components as 37 | distributed by the Copyright Holder(s). 38 | 39 | "Modified Version" refers to any derivative made by adding to, deleting, 40 | or substituting -- in part or in whole -- any of the components of the 41 | Original Version, by changing formats or by porting the Font Software to a 42 | new environment. 43 | 44 | "Author" refers to any designer, engineer, programmer, technical 45 | writer or other person who contributed to the Font Software. 46 | 47 | PERMISSION & CONDITIONS 48 | Permission is hereby granted, free of charge, to any person obtaining 49 | a copy of the Font Software, to use, study, copy, merge, embed, modify, 50 | redistribute, and sell modified and unmodified copies of the Font 51 | Software, subject to the following conditions: 52 | 53 | 1) Neither the Font Software nor any of its individual components, 54 | in Original or Modified Versions, may be sold by itself. 55 | 56 | 2) Original or Modified Versions of the Font Software may be bundled, 57 | redistributed and/or sold with any software, provided that each copy 58 | contains the above copyright notice and this license. These can be 59 | included either as stand-alone text files, human-readable headers or 60 | in the appropriate machine-readable metadata fields within text or 61 | binary files as long as those fields can be easily viewed by the user. 62 | 63 | 3) No Modified Version of the Font Software may use the Reserved Font 64 | Name(s) unless explicit written permission is granted by the corresponding 65 | Copyright Holder. This restriction only applies to the primary font name as 66 | presented to the users. 67 | 68 | 4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font 69 | Software shall not be used to promote, endorse or advertise any 70 | Modified Version, except to acknowledge the contribution(s) of the 71 | Copyright Holder(s) and the Author(s) or with their explicit written 72 | permission. 73 | 74 | 5) The Font Software, modified or unmodified, in part or in whole, 75 | must be distributed entirely under this license, and must not be 76 | distributed under any other license. The requirement for fonts to 77 | remain under this license does not apply to any document created 78 | using the Font Software. 79 | 80 | TERMINATION 81 | This license becomes null and void if any of the above conditions are 82 | not met. 83 | 84 | DISCLAIMER 85 | THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 86 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF 87 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT 88 | OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE 89 | COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 90 | INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL 91 | DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 92 | FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM 93 | OTHER DEALINGS IN THE FONT SOFTWARE. 94 | -------------------------------------------------------------------------------- /slick_slides/lib/fonts/OFL-jetbrainsmono.txt: -------------------------------------------------------------------------------- 1 | Copyright 2020 The JetBrains Mono Project Authors (https://github.com/JetBrains/JetBrainsMono) 2 | 3 | This Font Software is licensed under the SIL Open Font License, Version 1.1. 4 | This license is copied below, and is also available with a FAQ at: 5 | http://scripts.sil.org/OFL 6 | 7 | 8 | ----------------------------------------------------------- 9 | SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 10 | ----------------------------------------------------------- 11 | 12 | PREAMBLE 13 | The goals of the Open Font License (OFL) are to stimulate worldwide 14 | development of collaborative font projects, to support the font creation 15 | efforts of academic and linguistic communities, and to provide a free and 16 | open framework in which fonts may be shared and improved in partnership 17 | with others. 18 | 19 | The OFL allows the licensed fonts to be used, studied, modified and 20 | redistributed freely as long as they are not sold by themselves. The 21 | fonts, including any derivative works, can be bundled, embedded, 22 | redistributed and/or sold with any software provided that any reserved 23 | names are not used by derivative works. The fonts and derivatives, 24 | however, cannot be released under any other type of license. The 25 | requirement for fonts to remain under this license does not apply 26 | to any document created using the fonts or their derivatives. 27 | 28 | DEFINITIONS 29 | "Font Software" refers to the set of files released by the Copyright 30 | Holder(s) under this license and clearly marked as such. This may 31 | include source files, build scripts and documentation. 32 | 33 | "Reserved Font Name" refers to any names specified as such after the 34 | copyright statement(s). 35 | 36 | "Original Version" refers to the collection of Font Software components as 37 | distributed by the Copyright Holder(s). 38 | 39 | "Modified Version" refers to any derivative made by adding to, deleting, 40 | or substituting -- in part or in whole -- any of the components of the 41 | Original Version, by changing formats or by porting the Font Software to a 42 | new environment. 43 | 44 | "Author" refers to any designer, engineer, programmer, technical 45 | writer or other person who contributed to the Font Software. 46 | 47 | PERMISSION & CONDITIONS 48 | Permission is hereby granted, free of charge, to any person obtaining 49 | a copy of the Font Software, to use, study, copy, merge, embed, modify, 50 | redistribute, and sell modified and unmodified copies of the Font 51 | Software, subject to the following conditions: 52 | 53 | 1) Neither the Font Software nor any of its individual components, 54 | in Original or Modified Versions, may be sold by itself. 55 | 56 | 2) Original or Modified Versions of the Font Software may be bundled, 57 | redistributed and/or sold with any software, provided that each copy 58 | contains the above copyright notice and this license. These can be 59 | included either as stand-alone text files, human-readable headers or 60 | in the appropriate machine-readable metadata fields within text or 61 | binary files as long as those fields can be easily viewed by the user. 62 | 63 | 3) No Modified Version of the Font Software may use the Reserved Font 64 | Name(s) unless explicit written permission is granted by the corresponding 65 | Copyright Holder. This restriction only applies to the primary font name as 66 | presented to the users. 67 | 68 | 4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font 69 | Software shall not be used to promote, endorse or advertise any 70 | Modified Version, except to acknowledge the contribution(s) of the 71 | Copyright Holder(s) and the Author(s) or with their explicit written 72 | permission. 73 | 74 | 5) The Font Software, modified or unmodified, in part or in whole, 75 | must be distributed entirely under this license, and must not be 76 | distributed under any other license. The requirement for fonts to 77 | remain under this license does not apply to any document created 78 | using the Font Software. 79 | 80 | TERMINATION 81 | This license becomes null and void if any of the above conditions are 82 | not met. 83 | 84 | DISCLAIMER 85 | THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 86 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF 87 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT 88 | OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE 89 | COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 90 | INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL 91 | DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 92 | FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM 93 | OTHER DEALINGS IN THE FONT SOFTWARE. 94 | -------------------------------------------------------------------------------- /slick_slides/lib/fonts/inter.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/serverpod/slick_slides/ecb9b35a41fae1536f6ebc4399bcd3995dc8c1ba/slick_slides/lib/fonts/inter.ttf -------------------------------------------------------------------------------- /slick_slides/lib/fonts/jetbrainsmono.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/serverpod/slick_slides/ecb9b35a41fae1536f6ebc4399bcd3995dc8c1ba/slick_slides/lib/fonts/jetbrainsmono.ttf -------------------------------------------------------------------------------- /slick_slides/lib/slick_slides.dart: -------------------------------------------------------------------------------- 1 | library slick_slides; 2 | 3 | export 'src/layouts/content.dart'; 4 | export 'src/layouts/title.dart'; 5 | export 'src/layouts/person.dart'; 6 | export 'src/layouts/video.dart'; 7 | export 'src/transitions/fade.dart'; 8 | export 'src/transitions/transition.dart'; 9 | export 'src/slides/animated_code.dart'; 10 | export 'src/slides/bullets.dart'; 11 | export 'src/slides/full_screen_image.dart'; 12 | export 'src/slides/person.dart'; 13 | export 'src/slides/title.dart'; 14 | export 'src/slides/video.dart'; 15 | export 'src/widgets/bullets.dart'; 16 | export 'src/widgets/colored_code.dart'; 17 | export 'src/widgets/gradient_text.dart'; 18 | export 'src/deck/deck.dart'; 19 | export 'src/deck/theme.dart'; 20 | -------------------------------------------------------------------------------- /slick_slides/lib/src/deck/deck_controls.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | /// Controls for navigating between slides in a [SlideDeck]. The controls fade 4 | /// in and out based on the [visible] property. 5 | class DeckControls extends StatefulWidget { 6 | /// Creates a [DeckControls]. 7 | const DeckControls({ 8 | required this.onPrevious, 9 | required this.onNext, 10 | required this.onTogglePresenterView, 11 | this.visible = true, 12 | super.key, 13 | }); 14 | 15 | /// Called when the previous button is pressed. 16 | final VoidCallback onPrevious; 17 | 18 | /// Called when the next button is pressed. 19 | final VoidCallback onNext; 20 | 21 | /// Called when the toggle presenter mode button is pressed. 22 | final VoidCallback onTogglePresenterView; 23 | 24 | /// Whether the controls are visible. 25 | final bool visible; 26 | 27 | @override 28 | State createState() => _DeckControlsState(); 29 | } 30 | 31 | class _DeckControlsState extends State 32 | with SingleTickerProviderStateMixin { 33 | bool _visible = true; 34 | late AnimationController _controller; 35 | 36 | @override 37 | void initState() { 38 | super.initState(); 39 | _visible = widget.visible; 40 | _controller = AnimationController( 41 | vsync: this, 42 | duration: const Duration(milliseconds: 300), 43 | value: _visible ? 1 : 0, 44 | ); 45 | _controller.addListener(() { 46 | setState(() {}); 47 | }); 48 | } 49 | 50 | @override 51 | void dispose() { 52 | super.dispose(); 53 | _controller.dispose(); 54 | } 55 | 56 | @override 57 | void didUpdateWidget(DeckControls oldWidget) { 58 | super.didUpdateWidget(oldWidget); 59 | 60 | if (widget.visible != oldWidget.visible) { 61 | setState(() { 62 | _visible = widget.visible; 63 | if (_visible) { 64 | _controller.forward(); 65 | } else { 66 | _controller.reverse(); 67 | } 68 | }); 69 | } 70 | } 71 | 72 | @override 73 | Widget build(BuildContext context) { 74 | return Opacity( 75 | opacity: _controller.value, 76 | child: Container( 77 | decoration: BoxDecoration( 78 | color: Colors.black.withOpacity(0.5), 79 | borderRadius: BorderRadius.circular(24), 80 | ), 81 | padding: const EdgeInsets.all(8), 82 | child: Row( 83 | children: [ 84 | OutlinedButton( 85 | style: OutlinedButton.styleFrom( 86 | padding: const EdgeInsets.all(4), 87 | ), 88 | onPressed: widget.onTogglePresenterView, 89 | child: const Icon( 90 | Icons.speaker_notes_outlined, 91 | color: Colors.white, 92 | ), 93 | ), 94 | const SizedBox(width: 8), 95 | OutlinedButton( 96 | style: OutlinedButton.styleFrom( 97 | padding: const EdgeInsets.all(4), 98 | ), 99 | onPressed: widget.onPrevious, 100 | child: const Icon( 101 | Icons.chevron_left, 102 | color: Colors.white, 103 | ), 104 | ), 105 | const SizedBox(width: 8), 106 | OutlinedButton( 107 | style: OutlinedButton.styleFrom( 108 | padding: const EdgeInsets.all(4), 109 | ), 110 | onPressed: widget.onNext, 111 | child: const Icon( 112 | Icons.chevron_right, 113 | color: Colors.white, 114 | ), 115 | ), 116 | ], 117 | ), 118 | ), 119 | ); 120 | } 121 | } 122 | -------------------------------------------------------------------------------- /slick_slides/lib/src/deck/slide_config.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | /// Configuration used when building a [Slide]. 4 | class SlideConfigData { 5 | /// Creates a [SlideConfigData]. This is typically done by the [SlideDeck]. 6 | const SlideConfigData({ 7 | required this.animateIn, 8 | }); 9 | 10 | /// Whether the slide should animate in or be rendered in its final state 11 | /// immediately. 12 | final bool animateIn; 13 | } 14 | 15 | /// Inherited widget used to pass [SlideConfigData] down the widget tree. The 16 | /// configuration can be accessed using [SlideConfig.of] when building a 17 | /// [Slide]. 18 | class SlideConfig extends InheritedWidget { 19 | /// Creates a [SlideConfig]. This is typically done by the [SlideDeck]. 20 | const SlideConfig({ 21 | required this.data, 22 | required super.child, 23 | super.key, 24 | }); 25 | 26 | /// The build configuration for the slide. 27 | final SlideConfigData data; 28 | 29 | @override 30 | bool updateShouldNotify(SlideConfig oldWidget) => oldWidget.data != data; 31 | 32 | /// Returns the [SlideConfigData] for the given [context]. 33 | static SlideConfigData? of(BuildContext context) { 34 | return context.dependOnInheritedWidgetOfExactType()?.data; 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /slick_slides/lib/src/extensions/text_span.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | /// An extension which adds extra functionality to [TextSpan]. 4 | extension TextSpanExtension on TextSpan { 5 | /// Returns a copy of this [TextSpan] with the given [opacity] applied. 6 | TextSpan copyWithOpacity(double opacity) { 7 | TextStyle? newStyle; 8 | if (style != null && style!.color != null) { 9 | var oldOpacity = style!.color!.opacity; 10 | newStyle = style!.copyWith( 11 | color: style!.color!.withOpacity(opacity * oldOpacity), 12 | ); 13 | } 14 | 15 | List? newChildren; 16 | if (children != null) { 17 | newChildren = children!.map((child) { 18 | if (child is TextSpan) { 19 | return child.copyWithOpacity(opacity); 20 | } 21 | return child; 22 | }).toList(); 23 | } 24 | 25 | return TextSpan( 26 | text: text, 27 | children: newChildren, 28 | style: newStyle, 29 | recognizer: recognizer, 30 | semanticsLabel: semanticsLabel, 31 | mouseCursor: mouseCursor, 32 | onEnter: onEnter, 33 | onExit: onExit, 34 | locale: locale, 35 | spellOut: spellOut, 36 | ); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /slick_slides/lib/src/layouts/content.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:slick_slides/slick_slides.dart'; 3 | 4 | /// A basic layout for a slide. It can have a title, subtitle, and content. 5 | class ContentLayout extends StatelessWidget { 6 | /// Creates a basic layout for a slide. It can have a title, subtitle, and 7 | /// content. This layout is used by most types of slides. 8 | const ContentLayout({ 9 | this.title, 10 | this.subtitle, 11 | this.content, 12 | this.background, 13 | super.key, 14 | }); 15 | 16 | /// The title of the slide. 17 | final Widget? title; 18 | 19 | /// The subtitle of the slide. 20 | final Widget? subtitle; 21 | 22 | /// The background of the slide. 23 | final Widget? background; 24 | 25 | /// The content of the slide. 26 | final Widget? content; 27 | 28 | @override 29 | Widget build(BuildContext context) { 30 | var theme = SlideTheme.of(context)!; 31 | 32 | return Stack( 33 | fit: StackFit.expand, 34 | children: [ 35 | Positioned.fill( 36 | child: background ?? theme.backgroundBuilder(context), 37 | ), 38 | Padding( 39 | padding: theme.borderPadding, 40 | child: Column( 41 | crossAxisAlignment: CrossAxisAlignment.start, 42 | children: [ 43 | if (title != null) 44 | DefaultTextStyle( 45 | style: theme.textTheme.title, 46 | child: GradientText( 47 | gradient: theme.textTheme.titleGradient, 48 | child: title!, 49 | ), 50 | ), 51 | if (title != null && subtitle != null) 52 | SizedBox(height: theme.subtitleSpacing), 53 | if (subtitle != null) 54 | DefaultTextStyle( 55 | style: theme.textTheme.subtitle, 56 | child: GradientText( 57 | gradient: theme.textTheme.subtitleGradient, 58 | child: subtitle!, 59 | ), 60 | ), 61 | if (title != null || subtitle != null) 62 | SizedBox(height: theme.titleSpacing), 63 | if (content != null) Expanded(child: content!), 64 | ], 65 | ), 66 | ), 67 | ], 68 | ); 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /slick_slides/lib/src/layouts/person.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:slick_slides/slick_slides.dart'; 3 | 4 | /// The layout used by [PersonSlide]. 5 | class PersonLayout extends StatelessWidget { 6 | /// Creates a layout for a slide with a person's name, title, and image. 7 | const PersonLayout({ 8 | required this.name, 9 | required this.title, 10 | this.background, 11 | required this.image, 12 | Key? key, 13 | }) : super(key: key); 14 | 15 | /// The name of the person. 16 | final Widget name; 17 | 18 | /// The title of the person. 19 | final Widget title; 20 | 21 | /// The background of the slide. 22 | final Widget? background; 23 | 24 | /// The image of the person. 25 | final Widget image; 26 | 27 | @override 28 | Widget build(BuildContext context) { 29 | var theme = SlideTheme.of(context)!; 30 | 31 | return Stack( 32 | fit: StackFit.expand, 33 | children: [ 34 | Positioned.fill( 35 | child: background ?? theme.backgroundBuilder(context), 36 | ), 37 | Padding( 38 | padding: theme.borderPadding, 39 | child: Center( 40 | child: Row( 41 | mainAxisAlignment: MainAxisAlignment.center, 42 | children: [ 43 | Container( 44 | width: 512, 45 | height: 512, 46 | decoration: BoxDecoration( 47 | borderRadius: theme.imageBorderRadius, 48 | boxShadow: theme.imageBoxShadow, 49 | ), 50 | clipBehavior: Clip.antiAlias, 51 | child: FittedBox( 52 | fit: BoxFit.cover, 53 | child: image, 54 | ), 55 | ), 56 | SizedBox(width: theme.horizontalSpacing), 57 | Column( 58 | mainAxisAlignment: MainAxisAlignment.center, 59 | crossAxisAlignment: CrossAxisAlignment.start, 60 | children: [ 61 | DefaultTextStyle( 62 | style: theme.textTheme.title, 63 | textAlign: TextAlign.start, 64 | child: GradientText( 65 | gradient: theme.textTheme.titleGradient, 66 | child: name, 67 | ), 68 | ), 69 | Padding( 70 | padding: const EdgeInsets.only(top: 20.0), 71 | child: DefaultTextStyle( 72 | style: theme.textTheme.subtitle, 73 | textAlign: TextAlign.start, 74 | child: GradientText( 75 | gradient: theme.textTheme.subtitleGradient, 76 | child: title, 77 | ), 78 | ), 79 | ), 80 | ], 81 | ), 82 | ], 83 | ), 84 | ), 85 | ), 86 | ], 87 | ); 88 | } 89 | } 90 | -------------------------------------------------------------------------------- /slick_slides/lib/src/layouts/title.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:slick_slides/src/deck/theme.dart'; 3 | import 'package:slick_slides/src/widgets/gradient_text.dart'; 4 | 5 | /// The layout of a slide with a title and subtitle. 6 | class TitleLayout extends StatelessWidget { 7 | /// Creates a layout of a slide with a title and subtitle. 8 | const TitleLayout({ 9 | this.title, 10 | this.subtitle, 11 | this.alignment = Alignment.center, 12 | this.background, 13 | super.key, 14 | }); 15 | 16 | /// The title of the slide. 17 | final Widget? title; 18 | 19 | /// The subtitle of the slide. 20 | final Widget? subtitle; 21 | 22 | /// The background of the slide. 23 | final Widget? background; 24 | 25 | /// The alignment of the title and subtitle. Defaults to [Alignment.center] 26 | /// which centers the title and subtitle on the slide. 27 | final Alignment alignment; 28 | 29 | @override 30 | Widget build(BuildContext context) { 31 | var theme = SlideTheme.of(context)!; 32 | 33 | return Stack( 34 | fit: StackFit.expand, 35 | children: [ 36 | Positioned.fill( 37 | child: background ?? theme.backgroundBuilder(context), 38 | ), 39 | Padding( 40 | padding: theme.borderPadding, 41 | child: Align( 42 | alignment: alignment, 43 | child: Column( 44 | mainAxisAlignment: MainAxisAlignment.center, 45 | children: [ 46 | if (title != null) 47 | DefaultTextStyle( 48 | style: theme.textTheme.title, 49 | textAlign: TextAlign.center, 50 | child: GradientText( 51 | gradient: theme.textTheme.titleGradient, 52 | child: title!, 53 | ), 54 | ), 55 | if (subtitle != null) 56 | Padding( 57 | padding: const EdgeInsets.only(top: 20.0), 58 | child: DefaultTextStyle( 59 | style: theme.textTheme.subtitle, 60 | textAlign: TextAlign.center, 61 | child: GradientText( 62 | gradient: theme.textTheme.subtitleGradient, 63 | child: subtitle!, 64 | ), 65 | ), 66 | ), 67 | ], 68 | ), 69 | ), 70 | ), 71 | ], 72 | ); 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /slick_slides/lib/src/layouts/video.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:video_player/video_player.dart'; 3 | 4 | /// A layout that displays a video using the [VideoPlayer] widget. 5 | class VideoLayout extends StatelessWidget { 6 | /// The [VideoPlayerController] to used to play the video. 7 | final VideoPlayerController videoPlayerController; 8 | 9 | /// Creates a layout that displays a video using the [VideoPlayer] widget. 10 | const VideoLayout({ 11 | required this.videoPlayerController, 12 | super.key, 13 | }); 14 | 15 | @override 16 | Widget build(BuildContext context) { 17 | return VideoPlayer( 18 | videoPlayerController, 19 | ); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /slick_slides/lib/src/slides/animated_code.dart: -------------------------------------------------------------------------------- 1 | import 'package:audioplayers/audioplayers.dart'; 2 | import 'package:flutter/material.dart'; 3 | 4 | import 'package:slick_slides/slick_slides.dart'; 5 | 6 | /// Represents a code snippet with optionally highlighted lines. 7 | class FormattedCode { 8 | /// Creates a code snippet with optionally highlighted lines. 9 | FormattedCode({ 10 | required this.code, 11 | this.highlightedLines = const [], 12 | }); 13 | 14 | /// The code snippet. 15 | final String code; 16 | 17 | /// The lines to highlight. 18 | final List highlightedLines; 19 | } 20 | 21 | /// A slide that displays code and optionally animates between code snippets. 22 | class AnimatedCodeSlide extends Slide { 23 | /// Creates a slide that displays code and optionally animates between code 24 | /// snippets. Takes a list of [FormattedCode] objects, each of which contains 25 | /// a code snippet and optionally highlighted lines. 26 | AnimatedCodeSlide({ 27 | String? title, 28 | String? subtitle, 29 | required List formattedCode, 30 | String language = 'dart', 31 | WidgetBuilder? backgroundBuilder, 32 | String? notes, 33 | SlickTransition? transition, 34 | SlideThemeData? theme, 35 | Duration? autoplayDuration, 36 | Source? audioSource, 37 | }) : super.withSubSlides( 38 | builder: (context, index) { 39 | var highlightedLines = formattedCode[index].highlightedLines; 40 | var code = formattedCode[index].code; 41 | 42 | Widget content; 43 | if (index == 0) { 44 | content = ColoredCode( 45 | code: code, 46 | language: language, 47 | highlightedLines: highlightedLines, 48 | ); 49 | } else { 50 | content = ColoredCode( 51 | animateFromCode: formattedCode[index - 1].code, 52 | code: code, 53 | language: language, 54 | highlightedLines: highlightedLines, 55 | animateHighlightedLines: true, 56 | ); 57 | } 58 | 59 | return ContentLayout( 60 | title: title == null ? null : Text(title), 61 | subtitle: subtitle == null ? null : Text(subtitle), 62 | background: backgroundBuilder?.call(context), 63 | content: content, 64 | ); 65 | }, 66 | subSlideCount: formattedCode.length, 67 | notes: notes, 68 | transition: transition, 69 | theme: theme, 70 | autoplayDuration: autoplayDuration, 71 | audioSource: audioSource, 72 | ); 73 | } 74 | -------------------------------------------------------------------------------- /slick_slides/lib/src/slides/bullets.dart: -------------------------------------------------------------------------------- 1 | import 'package:audioplayers/audioplayers.dart'; 2 | import 'package:flutter/material.dart'; 3 | 4 | import 'package:slick_slides/slick_slides.dart'; 5 | 6 | /// The position of an image in a [BulletsSlide]. 7 | enum BulletsImageLocation { 8 | /// The image is on the left side of the slide. 9 | left, 10 | 11 | /// The image is on the right side of the slide. 12 | right, 13 | } 14 | 15 | /// A slide that displays a list of bullet points. 16 | class BulletsSlide extends Slide { 17 | /// Creates a slide that displays a list of bullet points based on [String]s. 18 | /// The [bullets] can either be shown all at once or one at a time by setting 19 | /// [bulletByBullet] to true. 20 | BulletsSlide({ 21 | String? title, 22 | String? subtitle, 23 | required List bullets, 24 | bool bulletByBullet = false, 25 | BulletsImageLocation imageLocation = BulletsImageLocation.right, 26 | AssetImage? image, 27 | WidgetBuilder? backgroundBuilder, 28 | String? notes, 29 | SlickTransition? transition, 30 | SlideThemeData? theme, 31 | Duration? autoplayDuration, 32 | Source? audioSource, 33 | }) : super.withSubSlides( 34 | builder: (context, index) { 35 | Widget content; 36 | if (image == null) { 37 | content = Bullets( 38 | bullets: bullets, 39 | animateLastVisibleBullet: bulletByBullet, 40 | numVisibleBullets: bulletByBullet ? index : null, 41 | ); 42 | } else { 43 | content = Row( 44 | crossAxisAlignment: CrossAxisAlignment.start, 45 | children: [ 46 | if (imageLocation == BulletsImageLocation.left) 47 | Expanded( 48 | child: Image( 49 | image: image, 50 | fit: BoxFit.contain, 51 | ), 52 | ), 53 | Expanded( 54 | child: Bullets( 55 | bullets: bullets, 56 | numVisibleBullets: bulletByBullet ? index : null, 57 | animateLastVisibleBullet: bulletByBullet, 58 | ), 59 | ), 60 | if (imageLocation == BulletsImageLocation.right) 61 | Expanded( 62 | child: Image( 63 | image: image, 64 | fit: BoxFit.contain, 65 | ), 66 | ), 67 | ], 68 | ); 69 | } 70 | 71 | return ContentLayout( 72 | title: title == null ? null : Text(title), 73 | subtitle: subtitle == null ? null : Text(subtitle), 74 | background: backgroundBuilder?.call(context), 75 | content: content, 76 | ); 77 | }, 78 | onPrecache: (context) async { 79 | if (image != null) { 80 | await precacheImage( 81 | image, 82 | context, 83 | ); 84 | } 85 | }, 86 | subSlideCount: bulletByBullet ? bullets.length + 1 : 1, 87 | notes: notes, 88 | transition: transition, 89 | theme: theme, 90 | autoplayDuration: autoplayDuration, 91 | audioSource: audioSource, 92 | ); 93 | 94 | /// Creates a slide that displays a list of bullet points based on [TextSpan]s. 95 | /// The [bullets] can either be shown all at once or one at a time by setting 96 | /// [bulletByBullet] to true. 97 | BulletsSlide.rich({ 98 | TextSpan? title, 99 | TextSpan? subtitle, 100 | required List bullets, 101 | bool bulletByBullet = false, 102 | BulletsImageLocation imageLocation = BulletsImageLocation.right, 103 | AssetImage? image, 104 | WidgetBuilder? backgroundBuilder, 105 | String? notes, 106 | SlickTransition? transition, 107 | SlideThemeData? theme, 108 | Duration? autoplayDuration, 109 | Source? audioSource, 110 | }) : super.withSubSlides( 111 | builder: (context, index) { 112 | Widget content; 113 | if (image == null) { 114 | content = Bullets.rich( 115 | bullets: bullets, 116 | animateLastVisibleBullet: bulletByBullet, 117 | numVisibleBullets: bulletByBullet ? index : null, 118 | ); 119 | } else { 120 | content = Row( 121 | crossAxisAlignment: CrossAxisAlignment.start, 122 | children: [ 123 | if (imageLocation == BulletsImageLocation.left) 124 | Expanded( 125 | child: Image( 126 | image: image, 127 | fit: BoxFit.contain, 128 | ), 129 | ), 130 | Expanded( 131 | child: Bullets.rich( 132 | bullets: bullets, 133 | numVisibleBullets: bulletByBullet ? index : null, 134 | animateLastVisibleBullet: bulletByBullet, 135 | ), 136 | ), 137 | if (imageLocation == BulletsImageLocation.right) 138 | Expanded( 139 | child: Image( 140 | image: image, 141 | fit: BoxFit.contain, 142 | ), 143 | ), 144 | ], 145 | ); 146 | } 147 | 148 | return ContentLayout( 149 | title: title == null ? null : Text.rich(title), 150 | subtitle: subtitle == null ? null : Text.rich(subtitle), 151 | background: backgroundBuilder?.call(context), 152 | content: content, 153 | ); 154 | }, 155 | onPrecache: (context) async { 156 | if (image != null) { 157 | await precacheImage( 158 | image, 159 | context, 160 | ); 161 | } 162 | }, 163 | subSlideCount: bulletByBullet ? bullets.length + 1 : 1, 164 | notes: notes, 165 | transition: transition, 166 | theme: theme, 167 | autoplayDuration: autoplayDuration, 168 | audioSource: audioSource, 169 | ); 170 | } 171 | -------------------------------------------------------------------------------- /slick_slides/lib/src/slides/full_screen_image.dart: -------------------------------------------------------------------------------- 1 | import 'package:audioplayers/audioplayers.dart'; 2 | import 'package:flutter/material.dart'; 3 | 4 | import 'package:slick_slides/slick_slides.dart'; 5 | 6 | /// A slide that displays a title and subtitle centered on the slide. 7 | class FullScreenImageSlide extends Slide { 8 | /// Creates a slide that displays a title and subtitle centered on the slide. 9 | FullScreenImageSlide({ 10 | required ImageProvider image, 11 | String? title, 12 | String? subtitle, 13 | Alignment alignment = Alignment.center, 14 | String? notes, 15 | SlickTransition? transition, 16 | final SlideThemeData? theme, 17 | Duration? autoplayDuration, 18 | Source? audioSource, 19 | }) : super( 20 | builder: (context) { 21 | return TitleLayout( 22 | title: title == null ? null : Text(title), 23 | subtitle: subtitle == null ? null : Text(subtitle), 24 | alignment: alignment, 25 | background: Image( 26 | image: image, 27 | fit: BoxFit.cover, 28 | ), 29 | ); 30 | }, 31 | onPrecache: (context) async { 32 | await precacheImage( 33 | image, 34 | context, 35 | ); 36 | }, 37 | notes: notes, 38 | transition: transition, 39 | theme: theme, 40 | autoplayDuration: autoplayDuration, 41 | audioSource: audioSource, 42 | ); 43 | 44 | /// Creates a slide that displays a title and subtitle centered on the slide. 45 | /// This constructor uses [TextSpan]s instead of [String]s for the title and 46 | /// subtitle to allow for rich text. 47 | FullScreenImageSlide.rich({ 48 | required ImageProvider image, 49 | TextSpan? title, 50 | TextSpan? subtitle, 51 | Alignment alignment = Alignment.center, 52 | WidgetBuilder? backgroundBuilder, 53 | String? notes, 54 | SlickTransition? transition, 55 | final SlideThemeData? theme, 56 | Duration? autoplayDuration, 57 | Source? audioSource, 58 | }) : super( 59 | builder: (context) { 60 | return TitleLayout( 61 | title: title == null ? null : Text.rich(title), 62 | subtitle: subtitle == null ? null : Text.rich(subtitle), 63 | alignment: alignment, 64 | background: Image( 65 | image: image, 66 | fit: BoxFit.cover, 67 | ), 68 | ); 69 | }, 70 | onPrecache: (context) async { 71 | await precacheImage( 72 | image, 73 | context, 74 | ); 75 | }, 76 | notes: notes, 77 | transition: transition, 78 | theme: theme, 79 | autoplayDuration: autoplayDuration, 80 | audioSource: audioSource, 81 | ); 82 | } 83 | -------------------------------------------------------------------------------- /slick_slides/lib/src/slides/person.dart: -------------------------------------------------------------------------------- 1 | import 'package:audioplayers/audioplayers.dart'; 2 | import 'package:flutter/material.dart'; 3 | 4 | import 'package:slick_slides/slick_slides.dart'; 5 | 6 | /// A slide that displays information about a person. It can have a name, title, 7 | /// and an image. 8 | class PersonSlide extends Slide { 9 | /// Creates a slide that displays information about a person. It can have a 10 | /// name, title, and an image. 11 | PersonSlide({ 12 | required String title, 13 | required String name, 14 | required ImageProvider image, 15 | String? notes, 16 | WidgetBuilder? backgroundBuilder, 17 | SlickTransition? transition, 18 | final SlideThemeData? theme, 19 | Duration? autoplayDuration, 20 | Source? audioSource, 21 | }) : super( 22 | builder: (context) { 23 | return PersonLayout( 24 | title: Text(title), 25 | name: Text(name), 26 | background: backgroundBuilder?.call(context), 27 | image: Image( 28 | image: image, 29 | ), 30 | ); 31 | }, 32 | onPrecache: (context) async { 33 | await precacheImage( 34 | image, 35 | context, 36 | ); 37 | }, 38 | notes: notes, 39 | transition: transition, 40 | theme: theme, 41 | autoplayDuration: autoplayDuration, 42 | audioSource: audioSource, 43 | ); 44 | 45 | /// Creates a slide that displays information about a person. It can have a 46 | /// name, title, and an image. This constructor uses [TextSpan]s instead of 47 | /// [String]s for the title and name to allow for rich text. 48 | PersonSlide.rich({ 49 | required TextSpan title, 50 | required TextSpan name, 51 | required ImageProvider image, 52 | String? notes, 53 | WidgetBuilder? backgroundBuilder, 54 | SlickTransition? transition, 55 | final SlideThemeData? theme, 56 | Duration? autoplayDuration, 57 | Source? audioSource, 58 | }) : super( 59 | builder: (context) { 60 | return PersonLayout( 61 | title: Text.rich(title), 62 | name: Text.rich(name), 63 | background: backgroundBuilder?.call(context), 64 | image: Image( 65 | image: image, 66 | ), 67 | ); 68 | }, 69 | onPrecache: (context) async { 70 | await precacheImage( 71 | image, 72 | context, 73 | ); 74 | }, 75 | notes: notes, 76 | transition: transition, 77 | theme: theme, 78 | autoplayDuration: autoplayDuration, 79 | audioSource: audioSource, 80 | ); 81 | } 82 | -------------------------------------------------------------------------------- /slick_slides/lib/src/slides/title.dart: -------------------------------------------------------------------------------- 1 | import 'package:audioplayers/audioplayers.dart'; 2 | import 'package:flutter/material.dart'; 3 | 4 | import 'package:slick_slides/slick_slides.dart'; 5 | 6 | /// A slide that displays a title and subtitle centered on the slide. 7 | class TitleSlide extends Slide { 8 | /// Creates a slide that displays a title and subtitle centered on the slide. 9 | TitleSlide({ 10 | required String title, 11 | String? subtitle, 12 | Alignment alignment = Alignment.center, 13 | WidgetBuilder? backgroundBuilder, 14 | String? notes, 15 | SlickTransition? transition, 16 | SlideThemeData? theme, 17 | Source? audioSource, 18 | Duration? autoplayDuration, 19 | }) : super( 20 | builder: (context) { 21 | return TitleLayout( 22 | title: Text(title), 23 | subtitle: subtitle == null ? null : Text(subtitle), 24 | alignment: alignment, 25 | background: backgroundBuilder?.call(context), 26 | ); 27 | }, 28 | notes: notes, 29 | transition: transition, 30 | theme: theme, 31 | audioSource: audioSource, 32 | autoplayDuration: autoplayDuration, 33 | ); 34 | 35 | /// Creates a slide that displays a title and subtitle centered on the slide. 36 | /// This constructor uses [TextSpan]s instead of [String]s for the title and 37 | /// subtitle to allow for rich text. 38 | TitleSlide.rich({ 39 | required TextSpan title, 40 | TextSpan? subtitle, 41 | Alignment alignment = Alignment.center, 42 | WidgetBuilder? backgroundBuilder, 43 | String? notes, 44 | SlickTransition? transition, 45 | SlideThemeData? theme, 46 | Source? audioSource, 47 | Duration? autoplayDuration, 48 | }) : super( 49 | builder: (context) { 50 | return TitleLayout( 51 | title: Text.rich(title), 52 | subtitle: subtitle == null ? null : Text.rich(subtitle), 53 | alignment: alignment, 54 | background: backgroundBuilder?.call(context), 55 | ); 56 | }, 57 | notes: notes, 58 | transition: transition, 59 | theme: theme, 60 | audioSource: audioSource, 61 | autoplayDuration: autoplayDuration, 62 | ); 63 | } 64 | -------------------------------------------------------------------------------- /slick_slides/lib/src/slides/video.dart: -------------------------------------------------------------------------------- 1 | import 'dart:async'; 2 | 3 | import 'package:audioplayers/audioplayers.dart'; 4 | import 'package:slick_slides/slick_slides.dart'; 5 | import 'package:video_player/video_player.dart'; 6 | 7 | /// A slide that displays a video. 8 | class VideoSlide extends Slide { 9 | /// The [VideoPlayerController] to used to play the video. The slide will 10 | /// control the video player, so it should not be used elsewhere. 11 | final VideoPlayerController videoPlayerController; 12 | 13 | /// Creates a slide that displays a video, filling the slide. 14 | VideoSlide({ 15 | required this.videoPlayerController, 16 | bool loop = false, 17 | Duration playAfterDuration = Duration.zero, 18 | String? notes, 19 | SlickTransition? transition, 20 | final SlideThemeData? theme, 21 | Duration? autoplayDuration, 22 | Source? audioSource, 23 | }) : super( 24 | builder: (context) { 25 | return VideoLayout( 26 | videoPlayerController: videoPlayerController, 27 | ); 28 | }, 29 | onPrecache: (context) async { 30 | await videoPlayerController.initialize(); 31 | videoPlayerController.setLooping(loop); 32 | }, 33 | onEnter: () async { 34 | await videoPlayerController.seekTo(Duration.zero); 35 | await Future.delayed(playAfterDuration); 36 | await videoPlayerController.play(); 37 | }, 38 | onExit: () async { 39 | await videoPlayerController.pause(); 40 | }, 41 | notes: notes, 42 | transition: transition, 43 | theme: theme, 44 | audioSource: audioSource, 45 | autoplayDuration: autoplayDuration, 46 | ); 47 | } 48 | -------------------------------------------------------------------------------- /slick_slides/lib/src/transitions/fade.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:slick_slides/slick_slides.dart'; 3 | 4 | /// A transition that fades between slides. If [color] is specified, the 5 | /// transition will fade through that color. 6 | class SlickFadeTransition extends SlickTransition { 7 | /// Creates a transition that fades between slides. If [color] is specified, 8 | /// the transition will fade through that color. 9 | const SlickFadeTransition({ 10 | super.duration = const Duration(milliseconds: 500), 11 | this.color, 12 | }); 13 | 14 | /// The color to fade through. If null, the transition will fade between the 15 | /// two slides. 16 | final Color? color; 17 | 18 | @override 19 | PageRoute buildPageRoute(WidgetBuilder slideBuilder) { 20 | if (color == null) { 21 | return _FadePageRoute( 22 | builder: slideBuilder, 23 | duration: duration, 24 | ); 25 | } else { 26 | return _FadeThroughColorPageRoute( 27 | builder: slideBuilder, 28 | duration: duration, 29 | color: color!, 30 | ); 31 | } 32 | } 33 | } 34 | 35 | class _FadePageRoute extends PageRoute { 36 | _FadePageRoute({ 37 | required this.builder, 38 | required this.duration, 39 | }); 40 | final WidgetBuilder builder; 41 | final Duration duration; 42 | 43 | @override 44 | Color get barrierColor => Colors.transparent; 45 | 46 | @override 47 | String get barrierLabel => 'barrier'; 48 | 49 | @override 50 | Widget buildPage(BuildContext context, Animation animation, 51 | Animation secondaryAnimation) { 52 | return FadeTransition( 53 | opacity: animation, 54 | child: builder(context), 55 | ); 56 | } 57 | 58 | @override 59 | bool get maintainState => true; 60 | 61 | @override 62 | Duration get transitionDuration => duration; 63 | } 64 | 65 | class _FadeThroughColorPageRoute extends PageRoute { 66 | _FadeThroughColorPageRoute({ 67 | required this.builder, 68 | required this.duration, 69 | required this.color, 70 | }); 71 | final WidgetBuilder builder; 72 | final Duration duration; 73 | final Color color; 74 | 75 | @override 76 | Color get barrierColor => Colors.transparent; 77 | 78 | @override 79 | String get barrierLabel => 'barrier'; 80 | 81 | @override 82 | Widget buildPage( 83 | BuildContext context, 84 | Animation animation, 85 | Animation secondaryAnimation, 86 | ) { 87 | var child = builder(context); 88 | return _FadeThroughColorTransition( 89 | color: color, 90 | animation: animation, 91 | child: child, 92 | ); 93 | } 94 | 95 | @override 96 | bool get maintainState => true; 97 | 98 | @override 99 | Duration get transitionDuration => duration; 100 | } 101 | 102 | class _FadeThroughColorTransition extends StatefulWidget { 103 | const _FadeThroughColorTransition({ 104 | required this.child, 105 | required this.color, 106 | required this.animation, 107 | Key? key, 108 | }) : super(key: key); 109 | 110 | final Widget child; 111 | final Color color; 112 | final Animation animation; 113 | 114 | @override 115 | _FadeThroughColorTransitionState createState() => 116 | _FadeThroughColorTransitionState(); 117 | } 118 | 119 | class _FadeThroughColorTransitionState extends State< 120 | _FadeThroughColorTransition> /*with SingleTickerProviderStateMixin*/ { 121 | @override 122 | void initState() { 123 | super.initState(); 124 | 125 | widget.animation.addListener(() { 126 | setState(() {}); 127 | }); 128 | } 129 | 130 | @override 131 | Widget build(BuildContext context) { 132 | if (widget.animation.value == 1.0) { 133 | return widget.child; 134 | } else if (widget.animation.value < 0.5) { 135 | var opacity = widget.animation.value * 2; 136 | return Container( 137 | color: widget.color.withOpacity(opacity), 138 | ); 139 | } else { 140 | var opacity = (1 - widget.animation.value) * 2; 141 | return Stack( 142 | children: [ 143 | widget.child, 144 | Container( 145 | color: widget.color.withOpacity(opacity), 146 | ) 147 | ], 148 | ); 149 | } 150 | } 151 | } 152 | -------------------------------------------------------------------------------- /slick_slides/lib/src/transitions/transition.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | /// A transition used when navigating between slides. 4 | abstract class SlickTransition { 5 | /// Creates a transition used when navigating between slides. 6 | const SlickTransition({ 7 | required this.duration, 8 | }); 9 | 10 | /// The duration of the transition. 11 | final Duration duration; 12 | 13 | /// Builds the [PageRoute] used to render the transition. 14 | PageRoute buildPageRoute(WidgetBuilder slideBuilder); 15 | } 16 | -------------------------------------------------------------------------------- /slick_slides/lib/src/widgets/bullets.dart: -------------------------------------------------------------------------------- 1 | // import 'package:auto_size_text/auto_size_text.dart'; 2 | import 'package:auto_size_text/auto_size_text.dart'; 3 | import 'package:flutter/material.dart'; 4 | import 'package:slick_slides/slick_slides.dart'; 5 | import 'package:slick_slides/src/deck/slide_config.dart'; 6 | import 'package:slick_slides/src/extensions/text_span.dart'; 7 | 8 | const _defaultBulletSpacing = 0.8; 9 | 10 | /// A widget that displays a list of bullets. [numVisibleBullets] can be used to 11 | /// control how many bullets should be displayed. The rest of the bullets will 12 | /// be hidden, but will still take up space. 13 | class Bullets extends StatefulWidget { 14 | /// Creates a widget that displays a list of bullets. [numVisibleBullets] can 15 | /// be used to control how many bullets should be displayed. The rest of the 16 | /// bullets will be hidden, but will still take up space. 17 | factory Bullets({ 18 | required List bullets, 19 | int? numVisibleBullets, 20 | double bulletSpacing = _defaultBulletSpacing, 21 | EdgeInsets? padding, 22 | bool animateLastVisibleBullet = false, 23 | Key? key, 24 | }) { 25 | var richBullets = bullets.map((e) => TextSpan(text: e)).toList(); 26 | return Bullets.rich( 27 | bullets: richBullets, 28 | numVisibleBullets: numVisibleBullets, 29 | bulletSpacing: bulletSpacing, 30 | padding: const EdgeInsets.symmetric(vertical: 50), 31 | animateLastVisibleBullet: animateLastVisibleBullet, 32 | key: key, 33 | ); 34 | } 35 | 36 | /// Creates a widget that displays a list of bullets. [numVisibleBullets] can 37 | /// be used to control how many bullets should be displayed. The rest of the 38 | /// bullets will be hidden, but will still take up space. This constructor 39 | /// uses [TextSpan]s instead of [String]s for the bullets to allow for rich 40 | /// text. 41 | const Bullets.rich({ 42 | required this.bullets, 43 | this.numVisibleBullets, 44 | this.bulletSpacing = _defaultBulletSpacing, 45 | this.padding = const EdgeInsets.symmetric(vertical: 50), 46 | this.animateLastVisibleBullet = false, 47 | super.key, 48 | }); 49 | 50 | /// The bullets to display. 51 | final List bullets; 52 | 53 | /// The number of bullets to display. The rest of the bullets will be hidden, 54 | /// but will still take up space. 55 | final int? numVisibleBullets; 56 | 57 | /// The spacing between bullets. 58 | final double bulletSpacing; 59 | 60 | /// The padding around the bullets. 61 | final EdgeInsets padding; 62 | 63 | /// If true, fade in the last bullet. 64 | final bool animateLastVisibleBullet; 65 | 66 | @override 67 | State createState() => _BulletsState(); 68 | } 69 | 70 | class _BulletsState extends State with SingleTickerProviderStateMixin { 71 | AnimationController? _controller; 72 | 73 | @override 74 | void initState() { 75 | super.initState(); 76 | 77 | if (widget.animateLastVisibleBullet) { 78 | _controller = AnimationController( 79 | vsync: this, 80 | duration: const Duration(milliseconds: 500), 81 | ); 82 | _controller!.addListener(() { 83 | setState(() {}); 84 | }); 85 | _controller!.forward(); 86 | } 87 | } 88 | 89 | @override 90 | void dispose() { 91 | _controller?.dispose(); 92 | super.dispose(); 93 | } 94 | 95 | @override 96 | Widget build(BuildContext context) { 97 | var theme = SlideTheme.of(context)!; 98 | var config = SlideConfig.of(context)!; 99 | var defaultTextColor = theme.textTheme.body.color!; 100 | 101 | var animate = config.animateIn && _controller != null; 102 | 103 | var joinedBulletsList = []; 104 | for (var i = 0; i < widget.bullets.length; i++) { 105 | if (animate) { 106 | // Animating last bullet. 107 | if (widget.numVisibleBullets != null && 108 | i >= widget.numVisibleBullets!) { 109 | // Draw bullets with transparent color if they are not visible. 110 | joinedBulletsList.add( 111 | TextSpan( 112 | style: const TextStyle(color: Colors.transparent), 113 | children: [widget.bullets[i].copyWithOpacity(0)], 114 | ), 115 | ); 116 | } else if (widget.numVisibleBullets != null && 117 | i == widget.numVisibleBullets! - 1) { 118 | // Fade in the last bullet. 119 | var opacity = _controller!.value; 120 | 121 | joinedBulletsList.add( 122 | TextSpan( 123 | style: TextStyle( 124 | color: defaultTextColor.withOpacity(opacity), 125 | ), 126 | children: [ 127 | widget.bullets[i].copyWithOpacity(opacity), 128 | ], 129 | ), 130 | ); 131 | } else { 132 | // Draw bullets with normal color if they are visible. 133 | joinedBulletsList.add(widget.bullets[i]); 134 | } 135 | } else { 136 | // Do not animate last bullet. 137 | if (widget.numVisibleBullets != null && 138 | i >= widget.numVisibleBullets!) { 139 | // Draw bullets with transparent color if they are not visible. 140 | joinedBulletsList.add( 141 | TextSpan( 142 | style: const TextStyle(color: Colors.transparent), 143 | children: [widget.bullets[i]], 144 | ), 145 | ); 146 | } else { 147 | // Draw bullets with normal color if they are visible. 148 | joinedBulletsList.add(widget.bullets[i]); 149 | } 150 | } 151 | 152 | // Add a new line between bullets. 153 | if (i != widget.bullets.length - 1) { 154 | joinedBulletsList.addAll([ 155 | const TextSpan( 156 | text: '\n', 157 | ), 158 | TextSpan( 159 | text: '\n', 160 | style: TextStyle( 161 | height: widget.bulletSpacing, 162 | ), 163 | ), 164 | ]); 165 | } 166 | } 167 | 168 | var joinedBullets = TextSpan( 169 | children: joinedBulletsList, 170 | ); 171 | 172 | return Padding( 173 | padding: widget.padding, 174 | child: DefaultTextStyle( 175 | style: theme.textTheme.body, 176 | child: AutoSizeText.rich(joinedBullets), 177 | ), 178 | ); 179 | } 180 | } 181 | -------------------------------------------------------------------------------- /slick_slides/lib/src/widgets/gradient_text.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | /// A widget that displays text with a gradient. 4 | class GradientText extends StatelessWidget { 5 | /// Creates a widget that displays text with a gradient. 6 | const GradientText({ 7 | required this.child, 8 | this.gradient, 9 | super.key, 10 | }); 11 | 12 | /// The text to display. 13 | final Widget child; 14 | 15 | /// The gradient to use for the text. 16 | final Gradient? gradient; 17 | 18 | @override 19 | Widget build(BuildContext context) { 20 | if (gradient == null) { 21 | return child; 22 | } 23 | 24 | return ShaderMask( 25 | shaderCallback: (bounds) => gradient!.createShader(bounds), 26 | child: child, 27 | ); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /slick_slides/misc/cover.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/serverpod/slick_slides/ecb9b35a41fae1536f6ebc4399bcd3995dc8c1ba/slick_slides/misc/cover.jpg -------------------------------------------------------------------------------- /slick_slides/pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: slick_slides 2 | description: Create a nice looking presentations in Flutter with animations and code. Intended for techical talks and videos. 3 | version: 0.2.1 4 | repository: https://github.com/serverpod/slick_slides 5 | topics: 6 | - presentation 7 | - slides 8 | 9 | environment: 10 | sdk: '>=3.0.5 <4.0.0' 11 | flutter: ">=1.17.0" 12 | 13 | 14 | dependencies: 15 | flutter: 16 | sdk: flutter 17 | auto_size_text: ^3.0.0 18 | audioplayers: ^5.2.1 19 | diff_match_patch: ^0.4.1 20 | syntax_highlight: ^0.3.0 21 | video_player: ^2.8.1 22 | 23 | dev_dependencies: 24 | flutter_test: 25 | sdk: flutter 26 | flutter_lints: ^2.0.0 27 | 28 | flutter: 29 | -------------------------------------------------------------------------------- /slick_slides_client/.gitignore: -------------------------------------------------------------------------------- 1 | # Files and directories created by pub 2 | .dart_tool/ 3 | .packages 4 | 5 | # Omit commiting pubspec.lock for library packages: 6 | # https://dart.dev/guides/libraries/private-files#pubspeclock 7 | pubspec.lock 8 | 9 | # Conventional directory for build outputs 10 | build/ 11 | 12 | # Directory created by dartdoc 13 | doc/api/ 14 | -------------------------------------------------------------------------------- /slick_slides_client/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | ## 1.0.0 2 | 3 | - Initial version, created by Stagehand 4 | -------------------------------------------------------------------------------- /slick_slides_client/README.md: -------------------------------------------------------------------------------- 1 | # slick_slides_client 2 | 3 | This is your Serverpod client. The code in here is mostly generated by 4 | Serverpod, but you may want to make changes if you are adding modules to your 5 | project. 6 | -------------------------------------------------------------------------------- /slick_slides_client/analysis_options.yaml: -------------------------------------------------------------------------------- 1 | # Defines a default set of lint rules enforced for 2 | # projects at Google. For details and rationale, 3 | # see https://github.com/dart-lang/pedantic#enabled-lints. 4 | 5 | # For lint rules and documentation, see http://dart-lang.github.io/linter/lints. 6 | # Uncomment to specify additional rules. 7 | # linter: 8 | # rules: 9 | # - camel_case_types 10 | 11 | analyzer: 12 | # exclude: 13 | # - path/to/excluded/files/** 14 | -------------------------------------------------------------------------------- /slick_slides_client/dartdoc_options.yaml: -------------------------------------------------------------------------------- 1 | dartdoc: 2 | categories: 3 | "Endpoint": 4 | markdown: doc/endpoint.md 5 | name: Endpoint -------------------------------------------------------------------------------- /slick_slides_client/doc/endpoint.md: -------------------------------------------------------------------------------- 1 | # Callable endpoints 2 | 3 | Each class contains callable methods that will call a method on the server side. These are normally defined in the `endpoint` directory in your server project. This client sends requests to these endpoints and returns the result. 4 | 5 | Example usage: 6 | 7 | ```dart 8 | // How to use ExampleEndpoint. 9 | client.example.hello("world!"); 10 | 11 | // Generic format. 12 | client..(...); 13 | ``` 14 | 15 | Please see the full official documentation [here](https://docs.serverpod.dev) 16 | -------------------------------------------------------------------------------- /slick_slides_client/lib/slick_slides_client.dart: -------------------------------------------------------------------------------- 1 | export 'src/protocol/protocol.dart'; 2 | export 'package:serverpod_client/serverpod_client.dart'; 3 | -------------------------------------------------------------------------------- /slick_slides_client/lib/src/protocol/client.dart: -------------------------------------------------------------------------------- 1 | /* AUTOMATICALLY GENERATED CODE DO NOT MODIFY */ 2 | /* To generate run: "serverpod generate" */ 3 | 4 | // ignore_for_file: library_private_types_in_public_api 5 | // ignore_for_file: public_member_api_docs 6 | // ignore_for_file: implementation_imports 7 | 8 | // ignore_for_file: no_leading_underscores_for_library_prefixes 9 | import 'package:serverpod_client/serverpod_client.dart' as _i1; 10 | import 'dart:async' as _i2; 11 | import 'dart:io' as _i3; 12 | import 'protocol.dart' as _i4; 13 | 14 | /// {@category Endpoint} 15 | class EndpointExample extends _i1.EndpointRef { 16 | EndpointExample(_i1.EndpointCaller caller) : super(caller); 17 | 18 | @override 19 | String get name => 'example'; 20 | 21 | _i2.Future hello(String name) => caller.callServerEndpoint( 22 | 'example', 23 | 'hello', 24 | {'name': name}, 25 | ); 26 | } 27 | 28 | class Client extends _i1.ServerpodClient { 29 | Client( 30 | String host, { 31 | _i3.SecurityContext? context, 32 | _i1.AuthenticationKeyManager? authenticationKeyManager, 33 | }) : super( 34 | host, 35 | _i4.Protocol(), 36 | context: context, 37 | authenticationKeyManager: authenticationKeyManager, 38 | ) { 39 | example = EndpointExample(this); 40 | } 41 | 42 | late final EndpointExample example; 43 | 44 | @override 45 | Map get endpointRefLookup => {'example': example}; 46 | @override 47 | Map get moduleLookup => {}; 48 | } 49 | -------------------------------------------------------------------------------- /slick_slides_client/lib/src/protocol/example.dart: -------------------------------------------------------------------------------- 1 | /* AUTOMATICALLY GENERATED CODE DO NOT MODIFY */ 2 | /* To generate run: "serverpod generate" */ 3 | 4 | // ignore_for_file: library_private_types_in_public_api 5 | // ignore_for_file: public_member_api_docs 6 | // ignore_for_file: implementation_imports 7 | 8 | // ignore_for_file: no_leading_underscores_for_library_prefixes 9 | import 'package:serverpod_client/serverpod_client.dart' as _i1; 10 | 11 | class Example extends _i1.SerializableEntity { 12 | Example({ 13 | required this.name, 14 | required this.data, 15 | }); 16 | 17 | factory Example.fromJson( 18 | Map jsonSerialization, 19 | _i1.SerializationManager serializationManager, 20 | ) { 21 | return Example( 22 | name: serializationManager.deserialize(jsonSerialization['name']), 23 | data: serializationManager.deserialize(jsonSerialization['data']), 24 | ); 25 | } 26 | 27 | String name; 28 | 29 | int data; 30 | 31 | @override 32 | Map toJson() { 33 | return { 34 | 'name': name, 35 | 'data': data, 36 | }; 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /slick_slides_client/lib/src/protocol/protocol.dart: -------------------------------------------------------------------------------- 1 | /* AUTOMATICALLY GENERATED CODE DO NOT MODIFY */ 2 | /* To generate run: "serverpod generate" */ 3 | 4 | // ignore_for_file: library_private_types_in_public_api 5 | // ignore_for_file: public_member_api_docs 6 | // ignore_for_file: implementation_imports 7 | 8 | library protocol; // ignore_for_file: no_leading_underscores_for_library_prefixes 9 | 10 | import 'package:serverpod_client/serverpod_client.dart' as _i1; 11 | import 'example.dart' as _i2; 12 | export 'example.dart'; 13 | export 'client.dart'; 14 | 15 | class Protocol extends _i1.SerializationManager { 16 | Protocol._(); 17 | 18 | factory Protocol() => _instance; 19 | 20 | static final Map customConstructors = {}; 21 | 22 | static final Protocol _instance = Protocol._(); 23 | 24 | @override 25 | T deserialize( 26 | dynamic data, [ 27 | Type? t, 28 | ]) { 29 | t ??= T; 30 | if (customConstructors.containsKey(t)) { 31 | return customConstructors[t]!(data, this) as T; 32 | } 33 | if (t == _i2.Example) { 34 | return _i2.Example.fromJson(data, this) as T; 35 | } 36 | if (t == _i1.getType<_i2.Example?>()) { 37 | return (data != null ? _i2.Example.fromJson(data, this) : null) as T; 38 | } 39 | return super.deserialize(data, t); 40 | } 41 | 42 | @override 43 | String? getClassNameForObject(Object data) { 44 | if (data is _i2.Example) { 45 | return 'Example'; 46 | } 47 | return super.getClassNameForObject(data); 48 | } 49 | 50 | @override 51 | dynamic deserializeByClassName(Map data) { 52 | if (data['className'] == 'Example') { 53 | return deserialize<_i2.Example>(data['data']); 54 | } 55 | return super.deserializeByClassName(data); 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /slick_slides_client/pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: slick_slides_client 2 | description: Starting point for a Serverpod client. 3 | 4 | environment: 5 | sdk: '>=2.19.0 <4.0.0' 6 | 7 | dependencies: 8 | serverpod_client: 1.1.0 9 | -------------------------------------------------------------------------------- /slick_slides_server/.gcloudignore: -------------------------------------------------------------------------------- 1 | # Files and directories created by pub 2 | .dart_tool/ 3 | .packages 4 | 5 | # Conventional directory for build outputs 6 | build/ 7 | 8 | # Directory created by dartdoc 9 | doc/api/ 10 | -------------------------------------------------------------------------------- /slick_slides_server/.gitignore: -------------------------------------------------------------------------------- 1 | # Files and directories created by pub 2 | .dart_tool/ 3 | .packages 4 | 5 | # Conventional directory for build outputs 6 | build/ 7 | 8 | # Directory created by dartdoc 9 | doc/api/ 10 | 11 | # Passwords file 12 | config/passwords.yaml 13 | -------------------------------------------------------------------------------- /slick_slides_server/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | ## 1.0.0 2 | 3 | - Initial version, created by Stagehand 4 | -------------------------------------------------------------------------------- /slick_slides_server/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM dart:2.19.0 AS build 2 | 3 | WORKDIR /app 4 | COPY . . 5 | 6 | RUN dart pub get 7 | RUN dart compile exe bin/main.dart -o bin/main 8 | 9 | FROM busybox 10 | 11 | ENV runmode=development 12 | ENV serverid=default 13 | ENV logging=normal 14 | ENV role=monolith 15 | 16 | COPY --from=build /runtime/ / 17 | COPY --from=build /app/bin/main /app/bin/main 18 | COPY --from=build /app/config/ config/ 19 | COPY --from=build /app/generated/ generated/ 20 | COPY --from=build /app/web/ web/ 21 | 22 | EXPOSE 8080 23 | EXPOSE 8081 24 | EXPOSE 8082 25 | 26 | CMD app/bin/main --mode $runmode --server-id $serverid --logging $logging --role $role 27 | -------------------------------------------------------------------------------- /slick_slides_server/README.md: -------------------------------------------------------------------------------- 1 | # slick_slides_server 2 | 3 | This is the starting point for your Serverpod server. 4 | 5 | To run your server, you first need to start Postgres and Redis. It's easiest to do with Docker. 6 | 7 | docker compose up --build --detach 8 | 9 | Then you can start the Serverpod server. 10 | 11 | dart bin/main.dart 12 | 13 | When you are finished, you can shut down Serverpod with `Ctrl-C`, then stop Postgres and Redis. 14 | 15 | docker compose stop 16 | -------------------------------------------------------------------------------- /slick_slides_server/analysis_options.yaml: -------------------------------------------------------------------------------- 1 | # This file configures the static analysis results for your project (errors, 2 | # warnings, and lints). 3 | # 4 | # This enables the 'recommended' set of lints from `package:lints`. 5 | # This set helps identify many issues that may lead to problems when running 6 | # or consuming Dart code, and enforces writing Dart using a single, idiomatic 7 | # style and format. 8 | # 9 | # If you want a smaller set of lints you can change this to specify 10 | # 'package:lints/core.yaml'. These are just the most critical lints 11 | # (the recommended set includes the core lints). 12 | # The core lints are also what is used by pub.dev for scoring packages. 13 | 14 | include: package:lints/recommended.yaml 15 | 16 | # Uncomment the following section to specify additional rules. 17 | 18 | # linter: 19 | # rules: 20 | # - camel_case_types 21 | 22 | # analyzer: 23 | # exclude: 24 | # - path/to/excluded/files/** 25 | 26 | # For more information about the core and recommended set of lints, see 27 | # https://dart.dev/go/core-lints 28 | 29 | # For additional information about configuring this file, see 30 | # https://dart.dev/guides/language/analysis-options 31 | -------------------------------------------------------------------------------- /slick_slides_server/bin/main.dart: -------------------------------------------------------------------------------- 1 | import 'package:slick_slides_server/server.dart'; 2 | 3 | /// This is the starting point for your Serverpod server. Typically, there is 4 | /// no need to modify this file. 5 | void main(List args) { 6 | run(args); 7 | } 8 | -------------------------------------------------------------------------------- /slick_slides_server/config/development.yaml: -------------------------------------------------------------------------------- 1 | # This is the configuration file for your local development environment. By 2 | # default, it runs a single server on port 8080. To set up your server, you will 3 | # need to add the name of the database you are connecting to and the user name. 4 | # The password for the database is stored in the config/passwords.yaml. 5 | # 6 | # When running your server locally, the server ports are the same as the public 7 | # facing ports. 8 | 9 | # Configuration for the main API server. 10 | apiServer: 11 | port: 8080 12 | publicHost: localhost 13 | publicPort: 8080 14 | publicScheme: http 15 | 16 | # Configuration for the Insights server. 17 | insightsServer: 18 | port: 8081 19 | publicHost: localhost 20 | publicPort: 8081 21 | publicScheme: http 22 | 23 | # Configuration for the web server. 24 | webServer: 25 | port: 8082 26 | publicHost: localhost 27 | publicPort: 8082 28 | publicScheme: http 29 | 30 | # This is the database setup for your server. 31 | database: 32 | host: localhost 33 | port: 8090 34 | name: slick_slides 35 | user: postgres 36 | 37 | # This is the setup for Redis. 38 | redis: 39 | enabled: false 40 | host: localhost 41 | port: 8091 -------------------------------------------------------------------------------- /slick_slides_server/config/generator.yaml: -------------------------------------------------------------------------------- 1 | type: server 2 | 3 | client_package_path: ../slick_slides_client 4 | -------------------------------------------------------------------------------- /slick_slides_server/config/production.yaml: -------------------------------------------------------------------------------- 1 | # This is the configuration file for your production environment. 2 | # Typically, you will want to route the traffic through a load balancer 3 | # which adds SSL security through https. If you use Serverpod's standard 4 | # Terraform scripts to deploy your server, all you need to change in 5 | # this file is the examplepod.com domain name. 6 | 7 | # Configuration for the main API server. 8 | apiServer: 9 | port: 8080 10 | publicHost: api.examplepod.com 11 | publicPort: 443 12 | publicScheme: https 13 | 14 | # Configuration for the Insights server. 15 | insightsServer: 16 | port: 8081 17 | publicHost: insights.examplepod.com 18 | publicPort: 443 19 | publicScheme: https 20 | 21 | # Configuration for the web server. 22 | webServer: 23 | port: 8082 24 | publicHost: app.examplepod.com 25 | publicPort: 443 26 | publicScheme: https 27 | 28 | # This is the database setup for your servers. The default for the Google Cloud 29 | # Engine Terraform configuration is to connect on a private IP address. 30 | # If you are connecting on a public IP (e.g. on AWS or Google Cloud Run), you 31 | # connect on the public IP of the database e.g. database.examplepod.com. 32 | database: 33 | host: database.private-production.examplepod.com 34 | port: 5432 35 | name: serverpod 36 | user: postgres 37 | 38 | # This is the setup for Redis. The default for the Google Cloud Engine Terraform 39 | # configuration is to connect on a private IP address. 40 | # If you are connecting on a public IP (e.g. on AWS or Google Cloud Run), you 41 | # connect on the public IP of the database e.g. redis.examplepod.com. 42 | redis: 43 | enabled: false 44 | host: redis.private-production.examplepod.com 45 | port: 6379 46 | -------------------------------------------------------------------------------- /slick_slides_server/config/staging.yaml: -------------------------------------------------------------------------------- 1 | # This is the configuration file for your staging environment. The staging 2 | # environment is meant to resemble the production environment as much as 3 | # possible and may connect to production databases services and data. You use it 4 | # for final testing before deploying the production server. 5 | # 6 | # Typically, you will want to route the traffic through a load balancer 7 | # which adds SSL security through https. If you use Serverpod's standard 8 | # Terraform scripts to deploy your server, all you need to change in 9 | # this file is the examplepod.com domain name. 10 | 11 | # Configuration for the main API server. 12 | apiServer: 13 | port: 8080 14 | publicHost: api-staging.examplepod.com 15 | publicPort: 443 16 | publicScheme: https 17 | 18 | # Configuration for the Insights server. 19 | insightsServer: 20 | port: 8081 21 | publicHost: insights-staging.examplepod.com 22 | publicPort: 443 23 | publicScheme: https 24 | 25 | # Configuration for the web server. 26 | webServer: 27 | port: 8082 28 | publicHost: app-staging.examplepod.com 29 | publicPort: 443 30 | publicScheme: https 31 | 32 | # This is the database setup for your servers. The default for the Google Cloud 33 | # Engine Terraform configuration is to connect on a private IP address. 34 | # If you are connecting on a public IP (e.g. on AWS or Google Cloud Run), you 35 | # connect on the public IP of the database e.g. database-staging.examplepod.com. 36 | database: 37 | host: database.private-staging.examplepod.com 38 | port: 5432 39 | name: serverpod 40 | user: postgres 41 | 42 | # This is the setup for Redis. The default for the Google Cloud Engine Terraform 43 | # configuration is to connect on a private IP address. 44 | # If you are connecting on a public IP (e.g. on AWS or Google Cloud Run), you 45 | # connect on the public IP of the database e.g. redis-staging.examplepod.com. 46 | redis: 47 | enabled: false 48 | host: redis.private-staging.examplepod.com 49 | port: 6379 50 | -------------------------------------------------------------------------------- /slick_slides_server/deploy/aws/scripts/appspec.yml: -------------------------------------------------------------------------------- 1 | version: 0.0 2 | os: linux 3 | files: 4 | - source: /vendor/ 5 | destination: /home/ec2-user/serverpod/upload/vendor/ 6 | - source: /slick_slides_server/ 7 | destination: /home/ec2-user/serverpod/upload/slick_slides_server/ 8 | hooks: 9 | BeforeInstall: 10 | - location: slick_slides_server/deploy/aws/scripts/install_dependencies 11 | timeout: 300 12 | runas: root 13 | ApplicationStart: 14 | - location: slick_slides_server/deploy/aws/scripts/start_server 15 | timeout: 300 16 | runas: root 17 | -------------------------------------------------------------------------------- /slick_slides_server/deploy/aws/scripts/install_dependencies: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | cat > /lib/systemd/system/serverpod.service << EOF 3 | [Unit] 4 | Description=Serverpod server 5 | After=multi-user.target 6 | 7 | [Service] 8 | User=ec2-user 9 | WorkingDirectory=/home/ec2-user 10 | ExecStart=/home/ec2-user/serverpod/active/slick_slides_server/deploy/aws/scripts/run_serverpod 11 | Restart=always 12 | 13 | [Install] 14 | WantedBy=muti-user.target 15 | WantedBy=network-online.target 16 | EOF 17 | 18 | systemctl daemon-reload 19 | -------------------------------------------------------------------------------- /slick_slides_server/deploy/aws/scripts/run_serverpod: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | RUNMODE=$(cat /home/ec2-user/runmode) 3 | SERVER_ID=$(curl -s http://169.254.169.254/latest/meta-data/instance-id) 4 | cd /home/ec2-user/serverpod/active/slick_slides_server 5 | /usr/lib/dart/bin/dart --old_gen_heap_size=0 run bin/main.dill --mode $RUNMODE --server-id $SERVER_ID > /home/ec2-user/serverpod.log 2> /home/ec2-user/serverpod.err 6 | -------------------------------------------------------------------------------- /slick_slides_server/deploy/aws/scripts/start_server: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Make sure permissions are correct for the serverpod directory 4 | chown -R ec2-user:ec2-user /home/ec2-user/serverpod 5 | 6 | # Run pub get as ec2-user 7 | cd /home/ec2-user/serverpod/upload/slick_slides_server/ 8 | sudo -u ec2-user /usr/lib/dart/bin/dart pub get 9 | 10 | # Set correct permissions for start script 11 | chmod 755 deploy/aws/scripts/run_serverpod 12 | 13 | # Stop the server if it's running, copy files, and restart 14 | systemctl stop serverpod 15 | 16 | rm -rf /home/ec2-user/serverpod/active/ 17 | cp -rp /home/ec2-user/serverpod/upload/ /home/ec2-user/serverpod/active/ 18 | 19 | systemctl start serverpod 20 | -------------------------------------------------------------------------------- /slick_slides_server/deploy/aws/terraform/.gitignore: -------------------------------------------------------------------------------- 1 | .terraform/ 2 | -------------------------------------------------------------------------------- /slick_slides_server/deploy/aws/terraform/balancers-staging.tf: -------------------------------------------------------------------------------- 1 | # API load balancer setup 2 | 3 | resource "aws_lb" "serverpod_staging" { 4 | count = var.enable_staging_server ? 1 : 0 5 | 6 | name = "${var.project_name}-serverpod-staging" 7 | internal = false 8 | load_balancer_type = "application" 9 | security_groups = [aws_security_group.api.id] 10 | subnets = module.vpc.public_subnets 11 | } 12 | 13 | resource "aws_lb_listener" "api_staging" { 14 | count = var.enable_staging_server ? 1 : 0 15 | 16 | load_balancer_arn = aws_lb.serverpod_staging[0].arn 17 | port = "443" 18 | protocol = "HTTPS" 19 | certificate_arn = var.certificate_arn 20 | 21 | default_action { 22 | type = "forward" 23 | target_group_arn = aws_lb_target_group.api_staging[0].arn 24 | } 25 | } 26 | 27 | resource "aws_lb_target_group" "api_staging" { 28 | count = var.enable_staging_server ? 1 : 0 29 | 30 | name = "${var.project_name}-api-staging" 31 | port = 8080 32 | protocol = "HTTP" 33 | vpc_id = module.vpc.vpc_id 34 | } 35 | 36 | resource "aws_lb_listener_rule" "api_staging" { 37 | count = var.enable_staging_server ? 1 : 0 38 | 39 | listener_arn = aws_lb_listener.api_staging[0].arn 40 | priority = 100 41 | 42 | action { 43 | type = "forward" 44 | target_group_arn = aws_lb_target_group.api_staging[0].arn 45 | } 46 | 47 | condition { 48 | host_header { 49 | values = ["${var.subdomain_api_staging}.${var.top_domain}"] 50 | } 51 | } 52 | } 53 | 54 | resource "aws_autoscaling_attachment" "api_staging" { 55 | count = var.enable_staging_server ? 1 : 0 56 | 57 | autoscaling_group_name = aws_autoscaling_group.staging[0].id 58 | lb_target_group_arn = aws_lb_target_group.api_staging[0].arn 59 | } 60 | 61 | resource "aws_route53_record" "api_staging" { 62 | count = var.enable_staging_server ? 1 : 0 63 | 64 | zone_id = var.hosted_zone_id 65 | name = "${var.subdomain_api_staging}.${var.top_domain}" 66 | type = "CNAME" 67 | ttl = "300" 68 | records = ["${aws_lb.serverpod_staging[0].dns_name}"] 69 | } 70 | 71 | resource "aws_lb_target_group" "insights_staging" { 72 | count = var.enable_staging_server ? 1 : 0 73 | 74 | name = "${var.project_name}-insights-staging" 75 | port = 8081 76 | protocol = "HTTP" 77 | vpc_id = module.vpc.vpc_id 78 | } 79 | 80 | resource "aws_autoscaling_attachment" "insights_staging" { 81 | count = var.enable_staging_server ? 1 : 0 82 | 83 | autoscaling_group_name = aws_autoscaling_group.staging[0].id 84 | lb_target_group_arn = aws_lb_target_group.insights_staging[0].arn 85 | } 86 | 87 | resource "aws_lb_listener_rule" "insights_staging" { 88 | count = var.enable_staging_server ? 1 : 0 89 | 90 | listener_arn = aws_lb_listener.api_staging[0].arn 91 | priority = 99 92 | 93 | action { 94 | type = "forward" 95 | target_group_arn = aws_lb_target_group.insights_staging[0].arn 96 | } 97 | 98 | condition { 99 | host_header { 100 | values = ["${var.subdomain_insights_staging}.${var.top_domain}"] 101 | } 102 | } 103 | } 104 | 105 | resource "aws_route53_record" "insights_staging" { 106 | count = var.enable_staging_server ? 1 : 0 107 | 108 | zone_id = var.hosted_zone_id 109 | name = "${var.subdomain_insights_staging}.${var.top_domain}" 110 | type = "CNAME" 111 | ttl = "300" 112 | records = ["${aws_lb.serverpod_staging[0].dns_name}"] 113 | } 114 | 115 | resource "aws_lb_target_group" "web_staging" { 116 | count = var.enable_staging_server ? 1 : 0 117 | 118 | name = "${var.project_name}-web-staging" 119 | port = 8082 120 | protocol = "HTTP" 121 | vpc_id = module.vpc.vpc_id 122 | } 123 | 124 | resource "aws_autoscaling_attachment" "web_staging" { 125 | count = var.enable_staging_server ? 1 : 0 126 | 127 | autoscaling_group_name = aws_autoscaling_group.staging[0].id 128 | lb_target_group_arn = aws_lb_target_group.web_staging[0].arn 129 | } 130 | 131 | 132 | resource "aws_lb_listener" "web_staging" { 133 | count = var.enable_staging_server ? 1 : 0 134 | 135 | load_balancer_arn = aws_lb.serverpod_staging[0].arn 136 | port = "80" 137 | protocol = "HTTP" 138 | 139 | default_action { 140 | type = "forward" 141 | target_group_arn = aws_lb_target_group.web_staging[0].arn 142 | } 143 | } 144 | -------------------------------------------------------------------------------- /slick_slides_server/deploy/aws/terraform/balancers.tf: -------------------------------------------------------------------------------- 1 | # API load balancer setup 2 | 3 | resource "aws_lb" "serverpod" { 4 | name = "${var.project_name}-serverpod" 5 | internal = false 6 | load_balancer_type = "application" 7 | security_groups = [aws_security_group.api.id] 8 | subnets = module.vpc.public_subnets 9 | } 10 | 11 | resource "aws_security_group" "api" { 12 | name = "${var.project_name}-api" 13 | ingress { 14 | from_port = 443 15 | to_port = 443 16 | protocol = "tcp" 17 | cidr_blocks = ["0.0.0.0/0"] 18 | } 19 | 20 | ingress { 21 | from_port = 80 22 | to_port = 80 23 | protocol = "tcp" 24 | cidr_blocks = ["0.0.0.0/0"] 25 | } 26 | 27 | egress { 28 | from_port = 0 29 | to_port = 0 30 | protocol = "-1" 31 | cidr_blocks = ["0.0.0.0/0"] 32 | } 33 | 34 | vpc_id = module.vpc.vpc_id 35 | } 36 | 37 | resource "aws_lb_listener" "api" { 38 | load_balancer_arn = aws_lb.serverpod.arn 39 | port = "443" 40 | protocol = "HTTPS" 41 | certificate_arn = var.certificate_arn 42 | 43 | default_action { 44 | type = "forward" 45 | target_group_arn = aws_lb_target_group.api.arn 46 | } 47 | } 48 | 49 | resource "aws_lb_target_group" "api" { 50 | name = "${var.project_name}-api" 51 | port = 8080 52 | protocol = "HTTP" 53 | vpc_id = module.vpc.vpc_id 54 | } 55 | 56 | resource "aws_lb_listener_rule" "api" { 57 | listener_arn = aws_lb_listener.api.arn 58 | priority = 100 59 | 60 | action { 61 | type = "forward" 62 | target_group_arn = aws_lb_target_group.api.arn 63 | } 64 | 65 | condition { 66 | host_header { 67 | values = ["${var.subdomain_api}.${var.top_domain}"] 68 | } 69 | } 70 | } 71 | 72 | resource "aws_autoscaling_attachment" "api" { 73 | autoscaling_group_name = aws_autoscaling_group.serverpod.id 74 | lb_target_group_arn = aws_lb_target_group.api.arn 75 | } 76 | 77 | resource "aws_route53_record" "api" { 78 | zone_id = var.hosted_zone_id 79 | name = "${var.subdomain_api}.${var.top_domain}" 80 | type = "CNAME" 81 | ttl = "300" 82 | records = ["${aws_lb.serverpod.dns_name}"] 83 | } 84 | 85 | # Insights load balancer rules 86 | 87 | resource "aws_lb_target_group" "insights" { 88 | name = "${var.project_name}-insights" 89 | port = 8081 90 | protocol = "HTTP" 91 | vpc_id = module.vpc.vpc_id 92 | } 93 | 94 | resource "aws_autoscaling_attachment" "insights" { 95 | autoscaling_group_name = aws_autoscaling_group.serverpod.id 96 | lb_target_group_arn = aws_lb_target_group.insights.arn 97 | } 98 | 99 | resource "aws_lb_listener_rule" "insights" { 100 | listener_arn = aws_lb_listener.api.arn 101 | priority = 99 102 | 103 | action { 104 | type = "forward" 105 | target_group_arn = aws_lb_target_group.insights.arn 106 | } 107 | 108 | condition { 109 | host_header { 110 | values = ["${var.subdomain_insights}.${var.top_domain}"] 111 | } 112 | } 113 | } 114 | 115 | resource "aws_route53_record" "insights" { 116 | zone_id = var.hosted_zone_id 117 | name = "${var.subdomain_insights}.${var.top_domain}" 118 | type = "CNAME" 119 | ttl = "300" 120 | records = ["${aws_lb.serverpod.dns_name}"] 121 | } 122 | 123 | # Web server load balancer rules 124 | 125 | resource "aws_lb_target_group" "web" { 126 | name = "${var.project_name}-web" 127 | port = 8082 128 | protocol = "HTTP" 129 | vpc_id = module.vpc.vpc_id 130 | } 131 | 132 | resource "aws_autoscaling_attachment" "web" { 133 | autoscaling_group_name = aws_autoscaling_group.serverpod.id 134 | lb_target_group_arn = aws_lb_target_group.web.arn 135 | } 136 | 137 | resource "aws_lb_listener" "web" { 138 | load_balancer_arn = aws_lb.serverpod.arn 139 | port = "80" 140 | protocol = "HTTP" 141 | # certificate_arn = var.certificate_arn 142 | 143 | default_action { 144 | type = "forward" 145 | target_group_arn = aws_lb_target_group.web.arn 146 | } 147 | } 148 | 149 | -------------------------------------------------------------------------------- /slick_slides_server/deploy/aws/terraform/cloudfront-web-staging.tf: -------------------------------------------------------------------------------- 1 | locals { 2 | alb_origin_id_staging = "${var.project_name}-web-staging" 3 | } 4 | 5 | resource "aws_cloudfront_distribution" "web_staging" { 6 | count = var.enable_staging_server ? 1 : 0 7 | 8 | origin { 9 | origin_id = local.alb_origin_id_staging 10 | domain_name = aws_lb.serverpod_staging[0].dns_name 11 | custom_origin_config { 12 | http_port = 80 13 | https_port = 443 14 | origin_protocol_policy = "http-only" 15 | origin_ssl_protocols = ["SSLv3"] 16 | } 17 | } 18 | enabled = true 19 | 20 | aliases = ["${var.subdomain_web_staging}.${var.top_domain}"] 21 | 22 | default_cache_behavior { 23 | allowed_methods = ["HEAD", "DELETE", "POST", "GET", "OPTIONS", "PUT", "PATCH"] 24 | cached_methods = ["HEAD", "GET"] 25 | target_origin_id = local.alb_origin_id_staging 26 | 27 | forwarded_values { 28 | query_string = true 29 | 30 | cookies { 31 | forward = "all" 32 | } 33 | 34 | headers = ["*"] 35 | } 36 | 37 | viewer_protocol_policy = "redirect-to-https" 38 | min_ttl = 0 39 | default_ttl = 0 40 | max_ttl = 0 41 | } 42 | 43 | price_class = "PriceClass_100" 44 | 45 | viewer_certificate { 46 | acm_certificate_arn = var.cloudfront_certificate_arn 47 | ssl_support_method = "sni-only" 48 | } 49 | 50 | restrictions { 51 | geo_restriction { 52 | restriction_type = "none" 53 | } 54 | } 55 | } 56 | 57 | resource "aws_route53_record" "web_staging" { 58 | count = var.enable_staging_server ? 1 : 0 59 | 60 | zone_id = var.hosted_zone_id 61 | name = "${var.subdomain_web_staging}.${var.top_domain}" 62 | type = "CNAME" 63 | ttl = "300" 64 | records = ["${aws_cloudfront_distribution.web_staging[0].domain_name}"] 65 | } -------------------------------------------------------------------------------- /slick_slides_server/deploy/aws/terraform/cloudfront-web.tf: -------------------------------------------------------------------------------- 1 | locals { 2 | alb_origin_id = "${var.project_name}-web" 3 | } 4 | 5 | resource "aws_cloudfront_distribution" "web" { 6 | origin { 7 | origin_id = local.alb_origin_id 8 | domain_name = aws_lb.serverpod.dns_name 9 | custom_origin_config { 10 | http_port = 80 11 | https_port = 443 12 | origin_protocol_policy = "http-only" 13 | origin_ssl_protocols = ["SSLv3"] 14 | } 15 | } 16 | enabled = true 17 | 18 | aliases = ["${var.subdomain_web}.${var.top_domain}", "${var.top_domain}"] 19 | 20 | default_cache_behavior { 21 | allowed_methods = ["HEAD", "DELETE", "POST", "GET", "OPTIONS", "PUT", "PATCH"] 22 | cached_methods = ["HEAD", "GET"] 23 | target_origin_id = local.alb_origin_id 24 | 25 | forwarded_values { 26 | query_string = true 27 | 28 | cookies { 29 | forward = "all" 30 | } 31 | 32 | headers = ["*"] 33 | } 34 | 35 | viewer_protocol_policy = "redirect-to-https" 36 | min_ttl = 0 37 | default_ttl = 0 38 | max_ttl = 0 39 | } 40 | 41 | price_class = "PriceClass_100" 42 | 43 | viewer_certificate { 44 | acm_certificate_arn = var.cloudfront_certificate_arn 45 | ssl_support_method = "sni-only" 46 | } 47 | 48 | restrictions { 49 | geo_restriction { 50 | restriction_type = "none" 51 | } 52 | } 53 | } 54 | 55 | resource "aws_route53_record" "web" { 56 | zone_id = var.hosted_zone_id 57 | name = "${var.subdomain_web}.${var.top_domain}" 58 | type = "CNAME" 59 | ttl = "300" 60 | records = ["${aws_cloudfront_distribution.web.domain_name}"] 61 | } 62 | 63 | resource "aws_route53_record" "web_top_domain" { 64 | count = var.use_top_domain_for_web ? 1 : 0 65 | zone_id = var.hosted_zone_id 66 | name = var.top_domain 67 | type = "A" 68 | alias { 69 | name = aws_cloudfront_distribution.web.domain_name 70 | zone_id = aws_cloudfront_distribution.web.hosted_zone_id 71 | evaluate_target_health = false 72 | } 73 | } -------------------------------------------------------------------------------- /slick_slides_server/deploy/aws/terraform/code-deploy.tf: -------------------------------------------------------------------------------- 1 | 2 | # Code deploy setup 3 | 4 | resource "aws_iam_instance_profile" "codedeploy_profile" { 5 | name = "${var.project_name}-codedeploy-profile" 6 | role = aws_iam_role.codedeploy_role.name 7 | } 8 | 9 | resource "aws_iam_role" "codedeploy_role" { 10 | name = "${var.project_name}-codedeploy-role" 11 | 12 | assume_role_policy = < AMI Catalog in your AWS console.) 60 | # Note: For some regions the t2.micro is not available. If so, consult the AWS 61 | # documentation to find another instance type that suits your needs. 62 | instance_type = "t2.micro" 63 | instance_ami = "ami-0ca285d4c2cda3300" 64 | autoscaling_min_size = 1 65 | autoscaling_max_size = 1 66 | autoscaling_desired_capacity = 1 67 | 68 | 69 | # Setup an additional server cluster and associated load balancers for staging. 70 | # By default, the staging server uses the same database and Redis setup as the 71 | # production server. If you want to change this behavior you will need add 72 | # and edit the Terraform files. 73 | # Note: By turning this feature on, the server setup will no longer fit within 74 | # the AWS free tier as it will use multiple server instances and load balancers. 75 | enable_staging_server = false 76 | 77 | staging_instance_type = "t2.micro" 78 | staging_autoscaling_min_size = 1 79 | staging_autoscaling_max_size = 1 80 | staging_autoscaling_desired_capacity = 1 81 | 82 | # The deployment bucket name needs to be unique and can only contain lower case 83 | # letters and dashes (no underscored allowed). 84 | deployment_bucket_name = "slick-slides-deployment-1661523" 85 | public_storage_bucket_name = "slick-slides-public-storage-1661523" 86 | private_storage_bucket_name = "slick-slides-private-storage-1661523" 87 | public_storage_bucket_name_staging = "slick-slides-public-storage-staging-1661523" 88 | private_storage_bucket_name_staging = "slick-slides-private-storage-staging-1661523" -------------------------------------------------------------------------------- /slick_slides_server/deploy/aws/terraform/database.tf: -------------------------------------------------------------------------------- 1 | resource "aws_db_instance" "postgres" { 2 | identifier = var.project_name 3 | allocated_storage = 10 4 | engine = "postgres" 5 | engine_version = "14.2" 6 | instance_class = "db.t3.micro" 7 | db_name = "serverpod" 8 | username = "postgres" 9 | password = var.DATABASE_PASSWORD_PRODUCTION 10 | skip_final_snapshot = true 11 | vpc_security_group_ids = [ 12 | aws_security_group.database.id 13 | ] 14 | publicly_accessible = true 15 | db_subnet_group_name = module.vpc.database_subnet_group_name 16 | } 17 | 18 | resource "aws_route53_record" "database" { 19 | zone_id = var.hosted_zone_id 20 | name = "${var.subdomain_database}.${var.top_domain}" 21 | type = "CNAME" 22 | ttl = "300" 23 | records = ["${aws_db_instance.postgres.address}"] 24 | } 25 | 26 | # Makes the database accessible from anywhere. 27 | resource "aws_security_group" "database" { 28 | name = "${var.project_name}-database" 29 | ingress { 30 | from_port = 5432 31 | to_port = 5432 32 | protocol = "tcp" 33 | cidr_blocks = ["0.0.0.0/0"] 34 | } 35 | } 36 | 37 | # Staging 38 | resource "aws_db_instance" "postgres_staging" { 39 | count = var.enable_staging_server ? 1 : 0 40 | 41 | identifier = "${var.project_name}-staging" 42 | allocated_storage = 10 43 | engine = "postgres" 44 | engine_version = "14.2" 45 | instance_class = "db.t3.micro" 46 | db_name = "serverpod" 47 | username = "postgres" 48 | password = var.DATABASE_PASSWORD_STAGING 49 | skip_final_snapshot = true 50 | vpc_security_group_ids = [ 51 | aws_security_group.database.id 52 | ] 53 | publicly_accessible = true 54 | db_subnet_group_name = module.vpc.database_subnet_group_name 55 | } 56 | 57 | resource "aws_route53_record" "database_staging" { 58 | count = var.enable_staging_server ? 1 : 0 59 | 60 | zone_id = var.hosted_zone_id 61 | name = "${var.subdomain_database_staging}.${var.top_domain}" 62 | type = "CNAME" 63 | ttl = "300" 64 | records = ["${aws_db_instance.postgres_staging[0].address}"] 65 | } -------------------------------------------------------------------------------- /slick_slides_server/deploy/aws/terraform/init-script.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | echo "Update yum packages" 3 | yum update -y 4 | 5 | # Install yum packages 6 | echo "Installing ruby" 7 | yum install ruby -y 8 | ehco "Installing wget" 9 | yum install wget -y 10 | 11 | # Install Dart 12 | echo "Installing dart" 13 | wget -q https://storage.googleapis.com/dart-archive/channels/stable/release/2.18.1/sdk/dartsdk-linux-x64-release.zip 14 | unzip -q dartsdk-linux-x64-release.zip 15 | sudo mv dart-sdk/ /usr/lib/dart/ 16 | sudo chmod -R 755 /usr/lib/dart/ 17 | echo 'export PATH="$PATH:/usr/lib/dart/bin"' >> /etc/profile.d/script.sh 18 | 19 | # Install CodeDeploy agent 20 | echo "Installing CodeDeploy agent" 21 | cd /home/ec2-user 22 | wget https://aws-codedeploy-us-west-2.s3.us-west-2.amazonaws.com/latest/install 23 | chmod +x ./install 24 | ./install auto 25 | rm install 26 | 27 | # Set runmode 28 | echo "Setting runmode" 29 | echo ${runmode} > /home/ec2-user/runmode 30 | chown ec2-user:ec2-user /home/ec2-user/runmode 31 | 32 | echo "Setup done" 33 | -------------------------------------------------------------------------------- /slick_slides_server/deploy/aws/terraform/instances.tf: -------------------------------------------------------------------------------- 1 | 2 | # EC2 auto scaling cluster and security groups 3 | 4 | data "aws_availability_zones" "available" { 5 | state = "available" 6 | } 7 | 8 | # TODO: Fix? 9 | data "aws_ami" "amazon-linux" { 10 | most_recent = true 11 | owners = ["amazon"] 12 | 13 | filter { 14 | name = "name" 15 | values = ["amzn-ami-hvm-*-x86_64-ebs"] 16 | } 17 | } 18 | 19 | resource "aws_launch_configuration" "serverpod" { 20 | name_prefix = "${var.project_name}-" 21 | image_id = var.instance_ami 22 | # image_id = data.aws_ami.amazon-linux.id 23 | instance_type = var.instance_type 24 | user_data = templatefile("init-script.sh", { runmode = "production" }) 25 | 26 | security_groups = [ 27 | aws_security_group.serverpod.id, 28 | aws_security_group.ssh.id 29 | ] 30 | 31 | iam_instance_profile = aws_iam_instance_profile.codedeploy_profile.name 32 | 33 | lifecycle { 34 | create_before_destroy = true 35 | } 36 | } 37 | 38 | resource "aws_autoscaling_group" "serverpod" { 39 | min_size = var.autoscaling_min_size 40 | max_size = var.autoscaling_max_size 41 | desired_capacity = var.autoscaling_desired_capacity 42 | launch_configuration = aws_launch_configuration.serverpod.name 43 | vpc_zone_identifier = module.vpc.public_subnets 44 | 45 | target_group_arns = [ 46 | aws_lb_target_group.api.arn, 47 | aws_lb_target_group.insights.arn, 48 | aws_lb_target_group.web.arn 49 | ] 50 | 51 | tag { 52 | key = "Name" 53 | value = "${var.project_name}-serverpod" 54 | propagate_at_launch = true 55 | } 56 | 57 | tag { 58 | key = "CodeDeploy" 59 | value = var.project_name 60 | propagate_at_launch = true 61 | } 62 | } 63 | 64 | resource "aws_security_group" "serverpod" { 65 | name = "${var.project_name}-serverpod" 66 | 67 | ingress { 68 | from_port = 8080 69 | to_port = 8082 70 | protocol = "tcp" 71 | security_groups = [aws_security_group.api.id] 72 | } 73 | 74 | egress { 75 | from_port = 0 76 | to_port = 0 77 | protocol = "-1" 78 | cidr_blocks = ["0.0.0.0/0"] 79 | } 80 | 81 | vpc_id = module.vpc.vpc_id 82 | } 83 | 84 | resource "aws_security_group" "ssh" { 85 | name = "${var.project_name}-ssh" 86 | 87 | ingress { 88 | from_port = 22 89 | to_port = 22 90 | protocol = "tcp" 91 | cidr_blocks = ["0.0.0.0/0"] 92 | } 93 | 94 | egress { 95 | from_port = 0 96 | to_port = 0 97 | protocol = "-1" 98 | cidr_blocks = ["0.0.0.0/0"] 99 | } 100 | 101 | vpc_id = module.vpc.vpc_id 102 | } 103 | -------------------------------------------------------------------------------- /slick_slides_server/deploy/aws/terraform/main.tf: -------------------------------------------------------------------------------- 1 | # Terraform and AWS setup 2 | 3 | terraform { 4 | required_providers { 5 | aws = { 6 | source = "hashicorp/aws" 7 | version = "~> 4.13" 8 | } 9 | } 10 | 11 | required_version = ">= 1.1.9" 12 | } 13 | 14 | provider "aws" { 15 | # profile = "default" 16 | region = var.aws_region 17 | } 18 | -------------------------------------------------------------------------------- /slick_slides_server/deploy/aws/terraform/redis.tf: -------------------------------------------------------------------------------- 1 | resource "aws_elasticache_cluster" "redis" { 2 | count = var.enable_redis ? 1 : 0 3 | 4 | cluster_id = var.project_name 5 | engine = "redis" 6 | node_type = "cache.t4g.micro" 7 | num_cache_nodes = 1 8 | engine_version = "6.x" 9 | port = 6379 10 | apply_immediately = true 11 | security_group_ids = [aws_security_group.redis[0].id] 12 | subnet_group_name = aws_elasticache_subnet_group.redis[0].name 13 | } 14 | 15 | resource "aws_route53_record" "redis" { 16 | count = var.enable_redis ? 1 : 0 17 | 18 | zone_id = var.hosted_zone_id 19 | name = "${var.subdomain_redis}.${var.top_domain}" 20 | type = "CNAME" 21 | ttl = "300" 22 | records = ["${aws_elasticache_cluster.redis[0].cache_nodes[0].address}"] 23 | } 24 | 25 | # Makes Redis accessible from the serverpod only. 26 | resource "aws_security_group" "redis" { 27 | count = var.enable_redis ? 1 : 0 28 | 29 | name = "${var.project_name}-redis" 30 | ingress { 31 | from_port = 6379 32 | to_port = 6379 33 | protocol = "tcp" 34 | security_groups = [aws_security_group.serverpod.id] 35 | } 36 | 37 | vpc_id = module.vpc.vpc_id 38 | } 39 | 40 | resource "aws_elasticache_subnet_group" "redis" { 41 | count = var.enable_redis ? 1 : 0 42 | 43 | name = "${var.project_name}-subnet" 44 | subnet_ids = module.vpc.public_subnets 45 | } 46 | 47 | # Staging 48 | resource "aws_elasticache_cluster" "redis_staging" { 49 | count = var.enable_redis && var.enable_staging_server ? 1 : 0 50 | 51 | cluster_id = var.project_name 52 | engine = "redis" 53 | node_type = "cache.t4g.micro" 54 | num_cache_nodes = 1 55 | engine_version = "6.x" 56 | port = 6379 57 | apply_immediately = true 58 | security_group_ids = [aws_security_group.redis[0].id] 59 | subnet_group_name = aws_elasticache_subnet_group.redis[0].name 60 | } 61 | 62 | resource "aws_route53_record" "redis_staging" { 63 | count = var.enable_redis && var.enable_staging_server ? 1 : 0 64 | 65 | zone_id = var.hosted_zone_id 66 | name = "${var.subdomain_redis_staging}.${var.top_domain}" 67 | type = "CNAME" 68 | ttl = "300" 69 | records = ["${aws_elasticache_cluster.redis_staging[0].cache_nodes[0].address}"] 70 | } -------------------------------------------------------------------------------- /slick_slides_server/deploy/aws/terraform/staging.tf: -------------------------------------------------------------------------------- 1 | resource "aws_launch_configuration" "staging" { 2 | count = var.enable_staging_server ? 1 : 0 3 | 4 | name_prefix = "${var.project_name}-staging-" 5 | image_id = var.instance_ami 6 | # image_id = data.aws_ami.amazon-linux.id 7 | instance_type = var.staging_instance_type 8 | user_data = templatefile("init-script.sh", { runmode = "staging" }) 9 | 10 | security_groups = [ 11 | aws_security_group.serverpod.id, 12 | aws_security_group.ssh.id 13 | ] 14 | 15 | iam_instance_profile = aws_iam_instance_profile.codedeploy_profile.name 16 | 17 | lifecycle { 18 | create_before_destroy = true 19 | } 20 | } 21 | 22 | resource "aws_autoscaling_group" "staging" { 23 | count = var.enable_staging_server ? 1 : 0 24 | 25 | min_size = var.staging_autoscaling_min_size 26 | max_size = var.staging_autoscaling_max_size 27 | desired_capacity = var.staging_autoscaling_desired_capacity 28 | launch_configuration = aws_launch_configuration.staging[0].name 29 | vpc_zone_identifier = module.vpc.public_subnets 30 | 31 | target_group_arns = [ 32 | aws_lb_target_group.api_staging[0].arn, 33 | aws_lb_target_group.insights_staging[0].arn, 34 | aws_lb_target_group.web_staging[0].arn 35 | ] 36 | 37 | tag { 38 | key = "Name" 39 | value = "${var.project_name}-serverpod-staging" 40 | propagate_at_launch = true 41 | } 42 | 43 | tag { 44 | key = "CodeDeploy" 45 | value = "${var.project_name}-staging" 46 | propagate_at_launch = true 47 | } 48 | } 49 | 50 | resource "aws_codedeploy_deployment_group" "staging" { 51 | count = var.enable_staging_server ? 1 : 0 52 | 53 | app_name = aws_codedeploy_app.serverpod.name 54 | deployment_group_name = "${var.project_name}-staging-group" 55 | service_role_arn = aws_iam_role.codedeploy_role.arn 56 | autoscaling_groups = [aws_autoscaling_group.staging[0].id] 57 | } -------------------------------------------------------------------------------- /slick_slides_server/deploy/aws/terraform/storage.tf: -------------------------------------------------------------------------------- 1 | # S3 buckets 2 | resource "aws_s3_bucket" "public_storage" { 3 | bucket = var.public_storage_bucket_name 4 | force_destroy = true 5 | 6 | tags = { 7 | Name = "${var.project_name} public storage" 8 | } 9 | } 10 | 11 | resource "aws_s3_bucket_acl" "public_storage" { 12 | bucket = aws_s3_bucket.public_storage.id 13 | acl = "private" 14 | } 15 | 16 | resource "aws_s3_bucket" "private_storage" { 17 | bucket = var.private_storage_bucket_name 18 | force_destroy = true 19 | 20 | tags = { 21 | Name = "${var.project_name} private storage" 22 | } 23 | } 24 | 25 | resource "aws_s3_bucket_acl" "private_storage" { 26 | bucket = aws_s3_bucket.private_storage.id 27 | acl = "private" 28 | } 29 | 30 | locals { 31 | s3_origin_id = "${var.project_name}-storage" 32 | } 33 | 34 | resource "aws_cloudfront_distribution" "public_storage" { 35 | origin { 36 | origin_id = local.s3_origin_id 37 | domain_name = aws_s3_bucket.public_storage.bucket_regional_domain_name 38 | } 39 | enabled = true 40 | 41 | aliases = ["${var.subdomain_storage}.${var.top_domain}"] 42 | 43 | default_cache_behavior { 44 | allowed_methods = ["GET", "HEAD"] 45 | cached_methods = ["GET", "HEAD"] 46 | target_origin_id = local.s3_origin_id 47 | 48 | forwarded_values { 49 | query_string = false 50 | cookies { 51 | forward = "none" 52 | } 53 | } 54 | viewer_protocol_policy = "redirect-to-https" 55 | min_ttl = 0 56 | default_ttl = 3600 57 | max_ttl = 86400 58 | } 59 | 60 | price_class = "PriceClass_100" 61 | 62 | viewer_certificate { 63 | acm_certificate_arn = var.cloudfront_certificate_arn 64 | ssl_support_method = "sni-only" 65 | } 66 | 67 | restrictions { 68 | geo_restriction { 69 | restriction_type = "none" 70 | } 71 | } 72 | } 73 | 74 | resource "aws_route53_record" "public_storage" { 75 | zone_id = var.hosted_zone_id 76 | name = "${var.subdomain_storage}.${var.top_domain}" 77 | type = "CNAME" 78 | ttl = "300" 79 | records = ["${aws_cloudfront_distribution.public_storage.domain_name}"] 80 | } -------------------------------------------------------------------------------- /slick_slides_server/deploy/aws/terraform/variables.tf: -------------------------------------------------------------------------------- 1 | # Project setup 2 | 3 | variable "project_name" { 4 | description = "Name of your project" 5 | type = string 6 | } 7 | 8 | variable "aws_region" { 9 | description = "The region to deploy the configuration to" 10 | type = string 11 | } 12 | 13 | variable "enable_redis" { 14 | description = "Deploy a managed Redis server" 15 | type = bool 16 | } 17 | 18 | variable "enable_staging_server" { 19 | description = "Deploy a staging server" 20 | type = bool 21 | } 22 | 23 | # Instance setup 24 | 25 | variable "instance_ami" { 26 | description = "The ami used for the instance" 27 | type = string 28 | } 29 | 30 | variable "instance_type" { 31 | description = "The type used for the instance" 32 | type = string 33 | } 34 | 35 | variable "autoscaling_min_size" { 36 | description = "Minimum size for the autoscaling pool" 37 | type = number 38 | } 39 | 40 | variable "autoscaling_max_size" { 41 | description = "Maximum size for the autoscaling pool" 42 | type = number 43 | } 44 | 45 | variable "autoscaling_desired_capacity" { 46 | description = "Desired size for the autoscaling pool" 47 | type = number 48 | } 49 | 50 | # Staging instance setup 51 | 52 | variable "staging_instance_type" { 53 | description = "The type used for the instance" 54 | type = string 55 | } 56 | 57 | variable "staging_autoscaling_min_size" { 58 | description = "Minimum size for the autoscaling pool" 59 | type = number 60 | } 61 | 62 | variable "staging_autoscaling_max_size" { 63 | description = "Maximum size for the autoscaling pool" 64 | type = number 65 | } 66 | 67 | variable "staging_autoscaling_desired_capacity" { 68 | description = "Desired size for the autoscaling pool" 69 | type = number 70 | } 71 | 72 | # Deployment 73 | 74 | variable "deployment_bucket_name" { 75 | description = "Name of S3 bucket used for deployments" 76 | type = string 77 | } 78 | 79 | # Domains and certificates 80 | 81 | variable "hosted_zone_id" { 82 | description = "The id of your hosted zone in Route 53" 83 | type = string 84 | } 85 | 86 | variable "certificate_arn" { 87 | description = "Wildcard certificate for the top domain" 88 | type = string 89 | } 90 | 91 | variable "cloudfront_certificate_arn" { 92 | description = "Certificate for use with Cloudfront, must be in us-east-1 region." 93 | type = string 94 | } 95 | 96 | variable "top_domain" { 97 | description = "The domain name for use with Insights api" 98 | type = string 99 | } 100 | 101 | variable "subdomain_database" { 102 | description = "The domain name for use with the database" 103 | type = string 104 | } 105 | 106 | variable "subdomain_redis" { 107 | description = "The domain name for use with Redis" 108 | type = string 109 | } 110 | 111 | variable "subdomain_api" { 112 | description = "The domain name for use with api" 113 | type = string 114 | } 115 | 116 | variable "subdomain_insights" { 117 | description = "The domain name for use with Insights api" 118 | type = string 119 | } 120 | 121 | variable "subdomain_web" { 122 | description = "The domain name for use with the web server" 123 | type = string 124 | } 125 | 126 | variable "subdomain_storage" { 127 | description = "The domain name for use with public storage" 128 | type = string 129 | } 130 | 131 | variable "subdomain_database_staging" { 132 | description = "The domain name for use with the database" 133 | type = string 134 | } 135 | 136 | variable "subdomain_redis_staging" { 137 | description = "The domain name for use with Redis" 138 | type = string 139 | } 140 | 141 | variable "subdomain_api_staging" { 142 | description = "The domain name for use by api staging" 143 | type = string 144 | } 145 | 146 | variable "subdomain_insights_staging" { 147 | description = "The domain name for use by insights staging" 148 | type = string 149 | } 150 | 151 | variable "subdomain_web_staging" { 152 | description = "The domain name for use by web server staging" 153 | type = string 154 | } 155 | 156 | variable "subdomain_storage_staging" { 157 | description = "The domain name for use with public storage" 158 | type = string 159 | } 160 | 161 | variable "use_top_domain_for_web" { 162 | description = "Set to true if you want to point the top domain to the web server" 163 | type = bool 164 | } 165 | 166 | # Storage 167 | 168 | variable "public_storage_bucket_name" { 169 | description = "Name of S3 bucket used for public storage" 170 | type = string 171 | } 172 | 173 | variable "private_storage_bucket_name" { 174 | description = "Name of S3 bucket used for private storage" 175 | type = string 176 | } 177 | 178 | variable "public_storage_bucket_name_staging" { 179 | description = "Name of S3 bucket used for public storage" 180 | type = string 181 | } 182 | 183 | variable "private_storage_bucket_name_staging" { 184 | description = "Name of S3 bucket used for private storage" 185 | type = string 186 | } 187 | 188 | # Database 189 | 190 | variable "DATABASE_PASSWORD_PRODUCTION" { 191 | description = "The production database password, you can find it in the config/passwords.yaml file." 192 | type = string 193 | } 194 | 195 | variable "DATABASE_PASSWORD_STAGING" { 196 | description = "The staging database password, you can find it in the config/passwords.yaml file (no need to specify if you aren't deployning a staging environment)." 197 | type = string 198 | } -------------------------------------------------------------------------------- /slick_slides_server/deploy/aws/terraform/vpc.tf: -------------------------------------------------------------------------------- 1 | module "vpc" { 2 | source = "terraform-aws-modules/vpc/aws" 3 | version = "2.77.0" 4 | 5 | name = "${var.project_name}-vpc" 6 | cidr = "10.0.0.0/16" 7 | 8 | azs = data.aws_availability_zones.available.names 9 | public_subnets = ["10.0.4.0/24", "10.0.5.0/24", "10.0.6.0/24"] 10 | enable_dns_hostnames = true 11 | enable_dns_support = true 12 | 13 | # create_database_subnet_group = true 14 | # create_database_subnet_route_table = true 15 | # create_database_internet_gateway_route = true 16 | 17 | # create_elasticache_subnet_group = true 18 | } 19 | -------------------------------------------------------------------------------- /slick_slides_server/deploy/gcp/console_gcr/cloud-run-deploy.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # These are the variables that need to be set to be able to deploy to cloud run. 4 | # You can find the values in the Google Cloud Console. 5 | DATABASE_INSTANCE_CONNECTION_NAME="" 6 | SERVICE_ACCOUNT="" 7 | 8 | # Optionally configure the region and runmode (staging is also viable). 9 | REGION="us-central1" 10 | RUNMODE="production" 11 | 12 | 13 | # Check that we are running the script from the correct directory. 14 | if [ ! -f config/production.yaml ]; then 15 | echo "Run this script from the root of your server directory (e.g., mypod/mypod_server)." 16 | exit 1 17 | fi 18 | 19 | 20 | # Deploy the API server. 21 | echo "Deploying API server..." 22 | 23 | gcloud run deploy serverpod-api \ 24 | --source=. \ 25 | --region=$REGION \ 26 | --platform=managed \ 27 | --service-account=$SERVICE_ACCOUNT \ 28 | --port=8080 \ 29 | --set-cloudsql-instances=$DATABASE_INSTANCE_CONNECTION_NAME \ 30 | --execution-environment=gen2 \ 31 | --set-env-vars="runmode=$RUNMODE" \ 32 | --set-env-vars="role=serverless" \ 33 | --allow-unauthenticated 34 | 35 | 36 | # Deploy the Insights server. This is used by the Serverpod Insights app. It 37 | # can provide run time information and logs from the API server. 38 | echo "Deploying Insights server..." 39 | 40 | gcloud run deploy serverpod-insights \ 41 | --source=. \ 42 | --region=$REGION \ 43 | --platform=managed \ 44 | --service-account=$SERVICE_ACCOUNT \ 45 | --port=8081 \ 46 | --set-cloudsql-instances=$DATABASE_INSTANCE_CONNECTION_NAME \ 47 | --execution-environment=gen2 \ 48 | --set-env-vars="runmode=$RUNMODE" \ 49 | --set-env-vars="role=serverless" \ 50 | --allow-unauthenticated 51 | -------------------------------------------------------------------------------- /slick_slides_server/deploy/gcp/terraform_gce/.gitignore: -------------------------------------------------------------------------------- 1 | credentials.json 2 | .terraform 3 | -------------------------------------------------------------------------------- /slick_slides_server/deploy/gcp/terraform_gce/config.auto.tfvars: -------------------------------------------------------------------------------- 1 | # This is the main configuration file. You can deploy your Serverpod by only 2 | # doing changes to this file. Serverpod uses a minimal setup by default, but 3 | # you can edit the main.tf file to choose higher tiers for database and your 4 | # managed instances or enable additional services like Redis. 5 | # 6 | # You can find complete setup instructions at: 7 | # https://docs.serverpod.dev/ 8 | 9 | # The Project ID from the Google Cloud Console. 10 | project = "" 11 | 12 | # The service account email address authorized by your Google Cloud Console. 13 | service_account_email = "" 14 | 15 | # The name of your DNS zone. 16 | dns_managed_zone = "" 17 | 18 | # The top domain of your DNS zone. e.g. "examplepod.com" 19 | top_domain = "" 20 | 21 | # The region and zone to use for the deployment. Default values work. 22 | region = "us-central1" 23 | zone = "us-central1-c" 24 | -------------------------------------------------------------------------------- /slick_slides_server/deploy/gcp/terraform_gce/main.tf: -------------------------------------------------------------------------------- 1 | # Set up and configure Terraform and the Google Cloud provider. 2 | terraform { 3 | required_providers { 4 | google = { 5 | source = "hashicorp/google" 6 | version = "4.51.0" 7 | } 8 | } 9 | } 10 | 11 | provider "google" { 12 | credentials = file("credentials.json") 13 | 14 | project = var.project 15 | region = var.region 16 | zone = var.zone 17 | } 18 | 19 | # Add a Serverpod module configured for production. Full documentation on all 20 | # options is available at: 21 | # https://github.com/serverpod/terraform-google-serverpod-cloud-engine 22 | 23 | module "serverpod_production" { 24 | # References the Serverpod module from GitHub. 25 | source = "github.com/serverpod/terraform-google-serverpod-cloud-engine?ref=stable-1.1" 26 | 27 | # Required parameters. 28 | project = var.project 29 | service_account_email = var.service_account_email 30 | 31 | runmode = "production" 32 | 33 | region = var.region 34 | zone = var.zone 35 | 36 | dns_managed_zone = var.dns_managed_zone 37 | top_domain = var.top_domain 38 | 39 | # Size of the auto scaling group. 40 | autoscaling_min_size = 1 41 | autoscaling_max_size = 2 42 | 43 | # Password for the production database. 44 | database_password = var.DATABASE_PASSWORD_PRODUCTION 45 | 46 | # Adds Cloud Storage buckets for file uploads. 47 | enable_storage = true 48 | 49 | # Adds Redis for caching and communication between servers. 50 | enable_redis = false 51 | 52 | # Makes it possible to SSH into the individual server instances. 53 | enable_ssh = true 54 | } 55 | 56 | 57 | # If you want to set up a staging environment, you can add a second module 58 | # configured for staging. Just uncomment the following code and change the 59 | # parameters as needed (default options should work too). 60 | 61 | # module "serverpod_staging" { 62 | # # References the Serverpod module from GitHub. 63 | # source = "github.com/serverpod/terraform-google-serverpod-cloud-engine?ref=stable-1.1" 64 | 65 | # # Required parameters. 66 | # project = var.project 67 | # service_account_email = var.service_account_email 68 | 69 | # runmode = "staging" 70 | 71 | # region = var.region 72 | # zone = var.zone 73 | 74 | # dns_managed_zone = var.dns_managed_zone 75 | # top_domain = var.top_domain 76 | 77 | # # Prefix for the staging, added to all subdomains. 78 | # subdomain_prefix = "staging-" 79 | 80 | # # Size of the auto scaling group. 81 | # autoscaling_min_size = 1 82 | # autoscaling_max_size = 2 83 | 84 | # # Password for the production database. 85 | # database_password = var.DATABASE_PASSWORD_STAGING 86 | 87 | # # Adds Cloud Storage buckets for file uploads. 88 | # enable_storage = true 89 | 90 | # # Adds Redis for caching and communication between servers. 91 | # enable_redis = false 92 | 93 | # # Makes it possible to SSH into the individual server instances. 94 | # enable_ssh = true 95 | # } 96 | -------------------------------------------------------------------------------- /slick_slides_server/deploy/gcp/terraform_gce/variables.tf: -------------------------------------------------------------------------------- 1 | # Project setup. 2 | 3 | variable "project" { 4 | type = string 5 | } 6 | 7 | variable "service_account_email" { 8 | type = string 9 | } 10 | 11 | variable "dns_managed_zone" { 12 | type = string 13 | } 14 | 15 | variable "top_domain" { 16 | type = string 17 | } 18 | 19 | variable "region" { 20 | type = string 21 | default = "us-central1" 22 | } 23 | 24 | variable "zone" { 25 | type = string 26 | default = "us-central1-c" 27 | } 28 | 29 | # Database 30 | 31 | variable "DATABASE_PASSWORD_PRODUCTION" { 32 | description = "The production database password, you can find it in the config/passwords.yaml file." 33 | type = string 34 | } 35 | 36 | variable "DATABASE_PASSWORD_STAGING" { 37 | description = "The staging database password, you can find it in the config/passwords.yaml file (no need to specify if you aren't deployning a staging environment)." 38 | type = string 39 | } 40 | -------------------------------------------------------------------------------- /slick_slides_server/docker-compose.yaml: -------------------------------------------------------------------------------- 1 | version: '3.7' 2 | 3 | services: 4 | postgres: 5 | image: postgres:14.1 6 | ports: 7 | - '8090:5432' 8 | environment: 9 | POSTGRES_USER: postgres 10 | POSTGRES_DB: slick_slides 11 | POSTGRES_PASSWORD: "zDqGC46-OQepMESlGvqUV6n33Y3-Q-ID" 12 | volumes: 13 | - slick_slides_data:/var/lib/postgresql/data 14 | redis: 15 | image: redis:6.2.6 16 | ports: 17 | - '8091:6379' 18 | command: redis-server --requirepass "emyWvT_3fFKDEYpO5H911MKd8bpQHE_Z" 19 | environment: 20 | - REDIS_REPLICATION_MODE=master 21 | volumes: 22 | slick_slides_data: 23 | -------------------------------------------------------------------------------- /slick_slides_server/generated/protocol.yaml: -------------------------------------------------------------------------------- 1 | example: 2 | - hello: 3 | -------------------------------------------------------------------------------- /slick_slides_server/generated/tables-serverpod.pgsql: -------------------------------------------------------------------------------- 1 | -- 2 | -- Class AuthKey as table serverpod_auth_key 3 | -- 4 | 5 | CREATE TABLE "serverpod_auth_key" ( 6 | "id" serial, 7 | "userId" integer NOT NULL, 8 | "hash" text NOT NULL, 9 | "scopeNames" json NOT NULL, 10 | "method" text NOT NULL 11 | ); 12 | 13 | ALTER TABLE ONLY "serverpod_auth_key" 14 | ADD CONSTRAINT serverpod_auth_key_pkey PRIMARY KEY (id); 15 | 16 | CREATE INDEX serverpod_auth_key_userId_idx ON "serverpod_auth_key" USING btree ("userId"); 17 | 18 | 19 | -- 20 | -- Class CloudStorageEntry as table serverpod_cloud_storage 21 | -- 22 | 23 | CREATE TABLE "serverpod_cloud_storage" ( 24 | "id" serial, 25 | "storageId" text NOT NULL, 26 | "path" text NOT NULL, 27 | "addedTime" timestamp without time zone NOT NULL, 28 | "expiration" timestamp without time zone, 29 | "byteData" bytea NOT NULL, 30 | "verified" boolean NOT NULL 31 | ); 32 | 33 | ALTER TABLE ONLY "serverpod_cloud_storage" 34 | ADD CONSTRAINT serverpod_cloud_storage_pkey PRIMARY KEY (id); 35 | 36 | CREATE UNIQUE INDEX serverpod_cloud_storage_path_idx ON "serverpod_cloud_storage" USING btree ("storageId", "path"); 37 | CREATE INDEX serverpod_cloud_storage_expiration ON "serverpod_cloud_storage" USING btree ("expiration"); 38 | 39 | 40 | -- 41 | -- Class CloudStorageDirectUploadEntry as table serverpod_cloud_storage_direct_upload 42 | -- 43 | 44 | CREATE TABLE "serverpod_cloud_storage_direct_upload" ( 45 | "id" serial, 46 | "storageId" text NOT NULL, 47 | "path" text NOT NULL, 48 | "expiration" timestamp without time zone NOT NULL, 49 | "authKey" text NOT NULL 50 | ); 51 | 52 | ALTER TABLE ONLY "serverpod_cloud_storage_direct_upload" 53 | ADD CONSTRAINT serverpod_cloud_storage_direct_upload_pkey PRIMARY KEY (id); 54 | 55 | CREATE UNIQUE INDEX serverpod_cloud_storage_direct_upload_storage_path ON "serverpod_cloud_storage_direct_upload" USING btree ("storageId", "path"); 56 | 57 | 58 | -- 59 | -- Class FutureCallEntry as table serverpod_future_call 60 | -- 61 | 62 | CREATE TABLE "serverpod_future_call" ( 63 | "id" serial, 64 | "name" text NOT NULL, 65 | "time" timestamp without time zone NOT NULL, 66 | "serializedObject" text, 67 | "serverId" text NOT NULL, 68 | "identifier" text 69 | ); 70 | 71 | ALTER TABLE ONLY "serverpod_future_call" 72 | ADD CONSTRAINT serverpod_future_call_pkey PRIMARY KEY (id); 73 | 74 | CREATE INDEX serverpod_future_call_time_idx ON "serverpod_future_call" USING btree ("time"); 75 | CREATE INDEX serverpod_future_call_serverId_idx ON "serverpod_future_call" USING btree ("serverId"); 76 | CREATE INDEX serverpod_future_call_identifier_idx ON "serverpod_future_call" USING btree ("identifier"); 77 | 78 | 79 | -- 80 | -- Class ServerHealthConnectionInfo as table serverpod_health_connection_info 81 | -- 82 | 83 | CREATE TABLE "serverpod_health_connection_info" ( 84 | "id" serial, 85 | "serverId" text NOT NULL, 86 | "timestamp" timestamp without time zone NOT NULL, 87 | "active" integer NOT NULL, 88 | "closing" integer NOT NULL, 89 | "idle" integer NOT NULL, 90 | "granularity" integer NOT NULL 91 | ); 92 | 93 | ALTER TABLE ONLY "serverpod_health_connection_info" 94 | ADD CONSTRAINT serverpod_health_connection_info_pkey PRIMARY KEY (id); 95 | 96 | CREATE UNIQUE INDEX serverpod_health_connection_info_timestamp_idx ON "serverpod_health_connection_info" USING btree ("timestamp", "serverId", "granularity"); 97 | 98 | 99 | -- 100 | -- Class ServerHealthMetric as table serverpod_health_metric 101 | -- 102 | 103 | CREATE TABLE "serverpod_health_metric" ( 104 | "id" serial, 105 | "name" text NOT NULL, 106 | "serverId" text NOT NULL, 107 | "timestamp" timestamp without time zone NOT NULL, 108 | "isHealthy" boolean NOT NULL, 109 | "value" double precision NOT NULL, 110 | "granularity" integer NOT NULL 111 | ); 112 | 113 | ALTER TABLE ONLY "serverpod_health_metric" 114 | ADD CONSTRAINT serverpod_health_metric_pkey PRIMARY KEY (id); 115 | 116 | CREATE UNIQUE INDEX serverpod_health_metric_timestamp_idx ON "serverpod_health_metric" USING btree ("timestamp", "serverId", "name", "granularity"); 117 | 118 | 119 | -- 120 | -- Class MethodInfo as table serverpod_method 121 | -- 122 | 123 | CREATE TABLE "serverpod_method" ( 124 | "id" serial, 125 | "endpoint" text NOT NULL, 126 | "method" text NOT NULL 127 | ); 128 | 129 | ALTER TABLE ONLY "serverpod_method" 130 | ADD CONSTRAINT serverpod_method_pkey PRIMARY KEY (id); 131 | 132 | CREATE UNIQUE INDEX serverpod_method_endpoint_method_idx ON "serverpod_method" USING btree ("endpoint", "method"); 133 | 134 | 135 | -- 136 | -- Class ReadWriteTestEntry as table serverpod_readwrite_test 137 | -- 138 | 139 | CREATE TABLE "serverpod_readwrite_test" ( 140 | "id" serial, 141 | "number" integer NOT NULL 142 | ); 143 | 144 | ALTER TABLE ONLY "serverpod_readwrite_test" 145 | ADD CONSTRAINT serverpod_readwrite_test_pkey PRIMARY KEY (id); 146 | 147 | 148 | -- 149 | -- Class RuntimeSettings as table serverpod_runtime_settings 150 | -- 151 | 152 | CREATE TABLE "serverpod_runtime_settings" ( 153 | "id" serial, 154 | "logSettings" json NOT NULL, 155 | "logSettingsOverrides" json NOT NULL, 156 | "logServiceCalls" boolean NOT NULL, 157 | "logMalformedCalls" boolean NOT NULL 158 | ); 159 | 160 | ALTER TABLE ONLY "serverpod_runtime_settings" 161 | ADD CONSTRAINT serverpod_runtime_settings_pkey PRIMARY KEY (id); 162 | 163 | 164 | -- 165 | -- Class SessionLogEntry as table serverpod_session_log 166 | -- 167 | 168 | CREATE TABLE "serverpod_session_log" ( 169 | "id" serial, 170 | "serverId" text NOT NULL, 171 | "time" timestamp without time zone NOT NULL, 172 | "module" text, 173 | "endpoint" text, 174 | "method" text, 175 | "duration" double precision, 176 | "numQueries" integer, 177 | "slow" boolean, 178 | "error" text, 179 | "stackTrace" text, 180 | "authenticatedUserId" integer, 181 | "isOpen" boolean, 182 | "touched" timestamp without time zone NOT NULL 183 | ); 184 | 185 | ALTER TABLE ONLY "serverpod_session_log" 186 | ADD CONSTRAINT serverpod_session_log_pkey PRIMARY KEY (id); 187 | 188 | CREATE INDEX serverpod_session_log_serverid_idx ON "serverpod_session_log" USING btree ("serverId"); 189 | CREATE INDEX serverpod_session_log_touched_idx ON "serverpod_session_log" USING btree ("touched"); 190 | CREATE INDEX serverpod_session_log_isopen_idx ON "serverpod_session_log" USING btree ("isOpen"); 191 | 192 | 193 | -- 194 | -- Class QueryLogEntry as table serverpod_query_log 195 | -- 196 | 197 | CREATE TABLE "serverpod_query_log" ( 198 | "id" serial, 199 | "serverId" text NOT NULL, 200 | "sessionLogId" integer NOT NULL, 201 | "messageId" integer, 202 | "query" text NOT NULL, 203 | "duration" double precision NOT NULL, 204 | "numRows" integer, 205 | "error" text, 206 | "stackTrace" text, 207 | "slow" boolean NOT NULL, 208 | "order" integer NOT NULL 209 | ); 210 | 211 | ALTER TABLE ONLY "serverpod_query_log" 212 | ADD CONSTRAINT serverpod_query_log_pkey PRIMARY KEY (id); 213 | 214 | CREATE INDEX serverpod_query_log_sessionLogId_idx ON "serverpod_query_log" USING btree ("sessionLogId"); 215 | 216 | ALTER TABLE ONLY "serverpod_query_log" 217 | ADD CONSTRAINT serverpod_query_log_fk_0 218 | FOREIGN KEY("sessionLogId") 219 | REFERENCES serverpod_session_log(id) 220 | ON DELETE CASCADE; 221 | 222 | -- 223 | -- Class MessageLogEntry as table serverpod_message_log 224 | -- 225 | 226 | CREATE TABLE "serverpod_message_log" ( 227 | "id" serial, 228 | "sessionLogId" integer NOT NULL, 229 | "serverId" text NOT NULL, 230 | "messageId" integer NOT NULL, 231 | "endpoint" text NOT NULL, 232 | "messageName" text NOT NULL, 233 | "duration" double precision NOT NULL, 234 | "error" text, 235 | "stackTrace" text, 236 | "slow" boolean NOT NULL, 237 | "order" integer NOT NULL 238 | ); 239 | 240 | ALTER TABLE ONLY "serverpod_message_log" 241 | ADD CONSTRAINT serverpod_message_log_pkey PRIMARY KEY (id); 242 | 243 | ALTER TABLE ONLY "serverpod_message_log" 244 | ADD CONSTRAINT serverpod_message_log_fk_0 245 | FOREIGN KEY("sessionLogId") 246 | REFERENCES serverpod_session_log(id) 247 | ON DELETE CASCADE; 248 | 249 | -- 250 | -- Class LogEntry as table serverpod_log 251 | -- 252 | 253 | CREATE TABLE "serverpod_log" ( 254 | "id" serial, 255 | "sessionLogId" integer NOT NULL, 256 | "messageId" integer, 257 | "reference" text, 258 | "serverId" text NOT NULL, 259 | "time" timestamp without time zone NOT NULL, 260 | "logLevel" integer NOT NULL, 261 | "message" text NOT NULL, 262 | "error" text, 263 | "stackTrace" text, 264 | "order" integer NOT NULL 265 | ); 266 | 267 | ALTER TABLE ONLY "serverpod_log" 268 | ADD CONSTRAINT serverpod_log_pkey PRIMARY KEY (id); 269 | 270 | CREATE INDEX serverpod_log_sessionLogId_idx ON "serverpod_log" USING btree ("sessionLogId"); 271 | 272 | ALTER TABLE ONLY "serverpod_log" 273 | ADD CONSTRAINT serverpod_log_fk_0 274 | FOREIGN KEY("sessionLogId") 275 | REFERENCES serverpod_session_log(id) 276 | ON DELETE CASCADE; 277 | 278 | -------------------------------------------------------------------------------- /slick_slides_server/generated/tables.pgsql: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/serverpod/slick_slides/ecb9b35a41fae1536f6ebc4399bcd3995dc8c1ba/slick_slides_server/generated/tables.pgsql -------------------------------------------------------------------------------- /slick_slides_server/lib/server.dart: -------------------------------------------------------------------------------- 1 | import 'package:serverpod/serverpod.dart'; 2 | 3 | import 'package:slick_slides_server/src/web/routes/root.dart'; 4 | 5 | import 'src/generated/protocol.dart'; 6 | import 'src/generated/endpoints.dart'; 7 | 8 | // This is the starting point of your Serverpod server. In most cases, you will 9 | // only need to make additions to this file if you add future calls, are 10 | // configuring Relic (Serverpod's web-server), or need custom setup work. 11 | 12 | void run(List args) async { 13 | // Initialize Serverpod and connect it with your generated code. 14 | final pod = Serverpod( 15 | args, 16 | Protocol(), 17 | Endpoints(), 18 | ); 19 | 20 | // If you are using any future calls, they need to be registered here. 21 | // pod.registerFutureCall(ExampleFutureCall(), 'exampleFutureCall'); 22 | 23 | // Setup a default page at the web root. 24 | pod.webServer.addRoute(RouteRoot(), '/'); 25 | pod.webServer.addRoute(RouteRoot(), '/index.html'); 26 | // Serve all files in the /static directory. 27 | pod.webServer.addRoute( 28 | RouteStaticDirectory(serverDirectory: 'static', basePath: '/'), 29 | '/*', 30 | ); 31 | 32 | // Start the server. 33 | await pod.start(); 34 | } 35 | -------------------------------------------------------------------------------- /slick_slides_server/lib/src/endpoints/example_endpoint.dart: -------------------------------------------------------------------------------- 1 | import 'package:serverpod/serverpod.dart'; 2 | 3 | // This is an example endpoint of your server. It's best practice to use the 4 | // `Endpoint` ending of the class name, but it will be removed when accessing 5 | // the endpoint from the client. I.e., this endpoint can be accessed through 6 | // `client.example` on the client side. 7 | 8 | // After adding or modifying an endpoint, you will need to run 9 | // `serverpod generate` to update the server and client code. 10 | class ExampleEndpoint extends Endpoint { 11 | // You create methods in your endpoint which are accessible from the client by 12 | // creating a public method with `Session` as its first parameter. Supported 13 | // parameter types are `bool`, `int`, `double`, `String`, `DateTime`, and any 14 | // objects that are generated from your `protocol` directory. The methods 15 | // should return a typed future; the same types as for the parameters are 16 | // supported. The `session` object provides access to the database, logging, 17 | // passwords, and information about the request being made to the server. 18 | Future hello(Session session, String name) async { 19 | return 'Hello $name'; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /slick_slides_server/lib/src/future_calls/example_future_call.dart: -------------------------------------------------------------------------------- 1 | import 'package:serverpod/serverpod.dart'; 2 | 3 | // Future calls are calls that will be invoked at a later time. An example is if 4 | // you want to send a drip-email campaign after a user signs up. You can 5 | // schedule a future call for a day, a week, or a month. The calls are stored in 6 | // the database, so they will persist even if the server is restarted. 7 | // 8 | // To add a future call to your server, you need to register it in the 9 | // `server.dart` file. Schedule the call using the 10 | // `session.serverpod.futureCallWithDelay` or `session.serverpod.futureCallAtTime` 11 | // methods. You can optionally pass a serializable object together with the 12 | // call. 13 | 14 | class ExampleFutureCall extends FutureCall { 15 | @override 16 | Future invoke(Session session, SerializableEntity? object) async { 17 | // Do something interesting in the future here. 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /slick_slides_server/lib/src/generated/endpoints.dart: -------------------------------------------------------------------------------- 1 | /* AUTOMATICALLY GENERATED CODE DO NOT MODIFY */ 2 | /* To generate run: "serverpod generate" */ 3 | 4 | // ignore_for_file: library_private_types_in_public_api 5 | // ignore_for_file: public_member_api_docs 6 | // ignore_for_file: implementation_imports 7 | 8 | // ignore_for_file: no_leading_underscores_for_library_prefixes 9 | import 'package:serverpod/serverpod.dart' as _i1; 10 | import '../endpoints/example_endpoint.dart' as _i2; 11 | 12 | class Endpoints extends _i1.EndpointDispatch { 13 | @override 14 | void initializeEndpoints(_i1.Server server) { 15 | var endpoints = { 16 | 'example': _i2.ExampleEndpoint() 17 | ..initialize( 18 | server, 19 | 'example', 20 | null, 21 | ) 22 | }; 23 | connectors['example'] = _i1.EndpointConnector( 24 | name: 'example', 25 | endpoint: endpoints['example']!, 26 | methodConnectors: { 27 | 'hello': _i1.MethodConnector( 28 | name: 'hello', 29 | params: { 30 | 'name': _i1.ParameterDescription( 31 | name: 'name', 32 | type: _i1.getType(), 33 | nullable: false, 34 | ) 35 | }, 36 | call: ( 37 | _i1.Session session, 38 | Map params, 39 | ) async => 40 | (endpoints['example'] as _i2.ExampleEndpoint).hello( 41 | session, 42 | params['name'], 43 | ), 44 | ) 45 | }, 46 | ); 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /slick_slides_server/lib/src/generated/example.dart: -------------------------------------------------------------------------------- 1 | /* AUTOMATICALLY GENERATED CODE DO NOT MODIFY */ 2 | /* To generate run: "serverpod generate" */ 3 | 4 | // ignore_for_file: library_private_types_in_public_api 5 | // ignore_for_file: public_member_api_docs 6 | // ignore_for_file: implementation_imports 7 | 8 | // ignore_for_file: no_leading_underscores_for_library_prefixes 9 | import 'package:serverpod/serverpod.dart' as _i1; 10 | 11 | class Example extends _i1.SerializableEntity { 12 | Example({ 13 | required this.name, 14 | required this.data, 15 | }); 16 | 17 | factory Example.fromJson( 18 | Map jsonSerialization, 19 | _i1.SerializationManager serializationManager, 20 | ) { 21 | return Example( 22 | name: serializationManager.deserialize(jsonSerialization['name']), 23 | data: serializationManager.deserialize(jsonSerialization['data']), 24 | ); 25 | } 26 | 27 | String name; 28 | 29 | int data; 30 | 31 | @override 32 | Map toJson() { 33 | return { 34 | 'name': name, 35 | 'data': data, 36 | }; 37 | } 38 | 39 | @override 40 | Map allToJson() { 41 | return { 42 | 'name': name, 43 | 'data': data, 44 | }; 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /slick_slides_server/lib/src/generated/protocol.dart: -------------------------------------------------------------------------------- 1 | /* AUTOMATICALLY GENERATED CODE DO NOT MODIFY */ 2 | /* To generate run: "serverpod generate" */ 3 | 4 | // ignore_for_file: library_private_types_in_public_api 5 | // ignore_for_file: public_member_api_docs 6 | // ignore_for_file: implementation_imports 7 | 8 | library protocol; // ignore_for_file: no_leading_underscores_for_library_prefixes 9 | 10 | import 'package:serverpod/serverpod.dart' as _i1; 11 | import 'package:serverpod/protocol.dart' as _i2; 12 | import 'example.dart' as _i3; 13 | export 'example.dart'; 14 | 15 | class Protocol extends _i1.SerializationManagerServer { 16 | Protocol._(); 17 | 18 | factory Protocol() => _instance; 19 | 20 | static final Map customConstructors = {}; 21 | 22 | static final Protocol _instance = Protocol._(); 23 | 24 | static final targetDatabaseDefinition = _i2.DatabaseDefinition( 25 | tables: [..._i2.Protocol.targetDatabaseDefinition.tables]); 26 | 27 | @override 28 | T deserialize( 29 | dynamic data, [ 30 | Type? t, 31 | ]) { 32 | t ??= T; 33 | if (customConstructors.containsKey(t)) { 34 | return customConstructors[t]!(data, this) as T; 35 | } 36 | if (t == _i3.Example) { 37 | return _i3.Example.fromJson(data, this) as T; 38 | } 39 | if (t == _i1.getType<_i3.Example?>()) { 40 | return (data != null ? _i3.Example.fromJson(data, this) : null) as T; 41 | } 42 | try { 43 | return _i2.Protocol().deserialize(data, t); 44 | } catch (_) {} 45 | return super.deserialize(data, t); 46 | } 47 | 48 | @override 49 | String? getClassNameForObject(Object data) { 50 | if (data is _i3.Example) { 51 | return 'Example'; 52 | } 53 | return super.getClassNameForObject(data); 54 | } 55 | 56 | @override 57 | dynamic deserializeByClassName(Map data) { 58 | if (data['className'] == 'Example') { 59 | return deserialize<_i3.Example>(data['data']); 60 | } 61 | return super.deserializeByClassName(data); 62 | } 63 | 64 | @override 65 | _i1.Table? getTableForType(Type t) { 66 | { 67 | var table = _i2.Protocol().getTableForType(t); 68 | if (table != null) { 69 | return table; 70 | } 71 | } 72 | return null; 73 | } 74 | 75 | @override 76 | _i2.DatabaseDefinition getTargetDatabaseDefinition() => 77 | targetDatabaseDefinition; 78 | } 79 | -------------------------------------------------------------------------------- /slick_slides_server/lib/src/protocol/example.yaml: -------------------------------------------------------------------------------- 1 | # Yaml-files in the `protocol` directory specify which serializable objects 2 | # should be generated. When you add or modify a file, you will need to run 3 | # `serverpod generate` to make the generated classes available in the server and 4 | # client. 5 | # 6 | # Please consult the documentation for more information on what you can add to 7 | # your yaml-files. 8 | 9 | 10 | # Name of the class to generate. 11 | class: Example 12 | 13 | # Add the table key, if this class represents a row in the database. 14 | #table: example 15 | 16 | # The fields (and columns if connected to the database) of the class. Supported 17 | # types are `bool`, `int`, `double`, `String`, `DateTime`, and any other 18 | # generated classes. You can also add lists of objects and types have support 19 | # for null safety. Eg. `List?` or `List`. 20 | fields: 21 | name: String 22 | data: int -------------------------------------------------------------------------------- /slick_slides_server/lib/src/web/routes/root.dart: -------------------------------------------------------------------------------- 1 | import 'dart:io'; 2 | 3 | import 'package:slick_slides_server/src/web/widgets/default_page_widget.dart'; 4 | import 'package:serverpod/serverpod.dart'; 5 | 6 | class RouteRoot extends WidgetRoute { 7 | @override 8 | Future build(Session session, HttpRequest request) async { 9 | return DefaultPageWidget(); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /slick_slides_server/lib/src/web/widgets/default_page_widget.dart: -------------------------------------------------------------------------------- 1 | import 'package:serverpod/serverpod.dart'; 2 | 3 | class DefaultPageWidget extends Widget { 4 | DefaultPageWidget() : super(name: 'default') { 5 | values = { 6 | 'served': DateTime.now(), 7 | 'runmode': Serverpod.instance!.runMode, 8 | }; 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /slick_slides_server/migrations/serverpod/20230522155355/definition.sql: -------------------------------------------------------------------------------- 1 | BEGIN; 2 | 3 | -- 4 | -- Class AuthKey as table serverpod_auth_key 5 | -- 6 | CREATE TABLE "serverpod_auth_key" ( 7 | "id" serial PRIMARY KEY, 8 | "userId" integer NOT NULL, 9 | "hash" text NOT NULL, 10 | "scopeNames" json NOT NULL, 11 | "method" text NOT NULL 12 | ); 13 | 14 | -- Indexes 15 | CREATE INDEX "serverpod_auth_key_userId_idx" ON "serverpod_auth_key" USING btree ("userId"); 16 | 17 | 18 | -- 19 | -- Class CloudStorageEntry as table serverpod_cloud_storage 20 | -- 21 | CREATE TABLE "serverpod_cloud_storage" ( 22 | "id" serial PRIMARY KEY, 23 | "storageId" text NOT NULL, 24 | "path" text NOT NULL, 25 | "addedTime" timestamp without time zone NOT NULL, 26 | "expiration" timestamp without time zone, 27 | "byteData" bytea NOT NULL, 28 | "verified" boolean NOT NULL 29 | ); 30 | 31 | -- Indexes 32 | CREATE UNIQUE INDEX "serverpod_cloud_storage_path_idx" ON "serverpod_cloud_storage" USING btree ("storageId", "path"); 33 | CREATE INDEX "serverpod_cloud_storage_expiration" ON "serverpod_cloud_storage" USING btree ("expiration"); 34 | 35 | 36 | -- 37 | -- Class CloudStorageDirectUploadEntry as table serverpod_cloud_storage_direct_upload 38 | -- 39 | CREATE TABLE "serverpod_cloud_storage_direct_upload" ( 40 | "id" serial PRIMARY KEY, 41 | "storageId" text NOT NULL, 42 | "path" text NOT NULL, 43 | "expiration" timestamp without time zone NOT NULL, 44 | "authKey" text NOT NULL 45 | ); 46 | 47 | -- Indexes 48 | CREATE UNIQUE INDEX "serverpod_cloud_storage_direct_upload_storage_path" ON "serverpod_cloud_storage_direct_upload" USING btree ("storageId", "path"); 49 | 50 | 51 | -- 52 | -- Class FutureCallEntry as table serverpod_future_call 53 | -- 54 | CREATE TABLE "serverpod_future_call" ( 55 | "id" serial PRIMARY KEY, 56 | "name" text NOT NULL, 57 | "time" timestamp without time zone NOT NULL, 58 | "serializedObject" text, 59 | "serverId" text NOT NULL, 60 | "identifier" text 61 | ); 62 | 63 | -- Indexes 64 | CREATE INDEX "serverpod_future_call_time_idx" ON "serverpod_future_call" USING btree ("time"); 65 | CREATE INDEX "serverpod_future_call_serverId_idx" ON "serverpod_future_call" USING btree ("serverId"); 66 | CREATE INDEX "serverpod_future_call_identifier_idx" ON "serverpod_future_call" USING btree ("identifier"); 67 | 68 | 69 | -- 70 | -- Class ServerHealthConnectionInfo as table serverpod_health_connection_info 71 | -- 72 | CREATE TABLE "serverpod_health_connection_info" ( 73 | "id" serial PRIMARY KEY, 74 | "serverId" text NOT NULL, 75 | "timestamp" timestamp without time zone NOT NULL, 76 | "active" integer NOT NULL, 77 | "closing" integer NOT NULL, 78 | "idle" integer NOT NULL, 79 | "granularity" integer NOT NULL 80 | ); 81 | 82 | -- Indexes 83 | CREATE UNIQUE INDEX "serverpod_health_connection_info_timestamp_idx" ON "serverpod_health_connection_info" USING btree ("timestamp", "serverId", "granularity"); 84 | 85 | 86 | -- 87 | -- Class ServerHealthMetric as table serverpod_health_metric 88 | -- 89 | CREATE TABLE "serverpod_health_metric" ( 90 | "id" serial PRIMARY KEY, 91 | "name" text NOT NULL, 92 | "serverId" text NOT NULL, 93 | "timestamp" timestamp without time zone NOT NULL, 94 | "isHealthy" boolean NOT NULL, 95 | "value" double precision NOT NULL, 96 | "granularity" integer NOT NULL 97 | ); 98 | 99 | -- Indexes 100 | CREATE UNIQUE INDEX "serverpod_health_metric_timestamp_idx" ON "serverpod_health_metric" USING btree ("timestamp", "serverId", "name", "granularity"); 101 | 102 | 103 | -- 104 | -- Class MethodInfo as table serverpod_method 105 | -- 106 | CREATE TABLE "serverpod_method" ( 107 | "id" serial PRIMARY KEY, 108 | "endpoint" text NOT NULL, 109 | "method" text NOT NULL 110 | ); 111 | 112 | -- Indexes 113 | CREATE UNIQUE INDEX "serverpod_method_endpoint_method_idx" ON "serverpod_method" USING btree ("endpoint", "method"); 114 | 115 | 116 | -- 117 | -- Class ReadWriteTestEntry as table serverpod_readwrite_test 118 | -- 119 | CREATE TABLE "serverpod_readwrite_test" ( 120 | "id" serial PRIMARY KEY, 121 | "number" integer NOT NULL 122 | ); 123 | 124 | 125 | -- 126 | -- Class RuntimeSettings as table serverpod_runtime_settings 127 | -- 128 | CREATE TABLE "serverpod_runtime_settings" ( 129 | "id" serial PRIMARY KEY, 130 | "logSettings" json NOT NULL, 131 | "logSettingsOverrides" json NOT NULL, 132 | "logServiceCalls" boolean NOT NULL, 133 | "logMalformedCalls" boolean NOT NULL 134 | ); 135 | 136 | 137 | -- 138 | -- Class SessionLogEntry as table serverpod_session_log 139 | -- 140 | CREATE TABLE "serverpod_session_log" ( 141 | "id" serial PRIMARY KEY, 142 | "serverId" text NOT NULL, 143 | "time" timestamp without time zone NOT NULL, 144 | "module" text, 145 | "endpoint" text, 146 | "method" text, 147 | "duration" double precision, 148 | "numQueries" integer, 149 | "slow" boolean, 150 | "error" text, 151 | "stackTrace" text, 152 | "authenticatedUserId" integer, 153 | "isOpen" boolean, 154 | "touched" timestamp without time zone NOT NULL 155 | ); 156 | 157 | -- Indexes 158 | CREATE INDEX "serverpod_session_log_serverid_idx" ON "serverpod_session_log" USING btree ("serverId"); 159 | CREATE INDEX "serverpod_session_log_touched_idx" ON "serverpod_session_log" USING btree ("touched"); 160 | CREATE INDEX "serverpod_session_log_isopen_idx" ON "serverpod_session_log" USING btree ("isOpen"); 161 | 162 | 163 | -- 164 | -- Class QueryLogEntry as table serverpod_query_log 165 | -- 166 | CREATE TABLE "serverpod_query_log" ( 167 | "id" serial PRIMARY KEY, 168 | "serverId" text NOT NULL, 169 | "sessionLogId" integer NOT NULL, 170 | "messageId" integer, 171 | "query" text NOT NULL, 172 | "duration" double precision NOT NULL, 173 | "numRows" integer, 174 | "error" text, 175 | "stackTrace" text, 176 | "slow" boolean NOT NULL, 177 | "order" integer NOT NULL 178 | ); 179 | 180 | -- Indexes 181 | CREATE INDEX "serverpod_query_log_sessionLogId_idx" ON "serverpod_query_log" USING btree ("sessionLogId"); 182 | 183 | -- Foreign keys 184 | ALTER TABLE ONLY "serverpod_query_log" 185 | ADD CONSTRAINT "serverpod_query_log_fk_0" 186 | FOREIGN KEY("sessionLogId") 187 | REFERENCES "serverpod_session_log"("id") 188 | ON DELETE CASCADE; 189 | 190 | 191 | -- 192 | -- Class MessageLogEntry as table serverpod_message_log 193 | -- 194 | CREATE TABLE "serverpod_message_log" ( 195 | "id" serial PRIMARY KEY, 196 | "sessionLogId" integer NOT NULL, 197 | "serverId" text NOT NULL, 198 | "messageId" integer NOT NULL, 199 | "endpoint" text NOT NULL, 200 | "messageName" text NOT NULL, 201 | "duration" double precision NOT NULL, 202 | "error" text, 203 | "stackTrace" text, 204 | "slow" boolean NOT NULL, 205 | "order" integer NOT NULL 206 | ); 207 | 208 | -- Foreign keys 209 | ALTER TABLE ONLY "serverpod_message_log" 210 | ADD CONSTRAINT "serverpod_message_log_fk_0" 211 | FOREIGN KEY("sessionLogId") 212 | REFERENCES "serverpod_session_log"("id") 213 | ON DELETE CASCADE; 214 | 215 | 216 | -- 217 | -- Class LogEntry as table serverpod_log 218 | -- 219 | CREATE TABLE "serverpod_log" ( 220 | "id" serial PRIMARY KEY, 221 | "sessionLogId" integer NOT NULL, 222 | "messageId" integer, 223 | "reference" text, 224 | "serverId" text NOT NULL, 225 | "time" timestamp without time zone NOT NULL, 226 | "logLevel" integer NOT NULL, 227 | "message" text NOT NULL, 228 | "error" text, 229 | "stackTrace" text, 230 | "order" integer NOT NULL 231 | ); 232 | 233 | -- Indexes 234 | CREATE INDEX "serverpod_log_sessionLogId_idx" ON "serverpod_log" USING btree ("sessionLogId"); 235 | 236 | -- Foreign keys 237 | ALTER TABLE ONLY "serverpod_log" 238 | ADD CONSTRAINT "serverpod_log_fk_0" 239 | FOREIGN KEY("sessionLogId") 240 | REFERENCES "serverpod_session_log"("id") 241 | ON DELETE CASCADE; 242 | 243 | 244 | -- 245 | -- MIGRATION 1.1.0 246 | -- 247 | INSERT INTO "serverpod_migrations" ("module", "version", "priority", "timestamp") 248 | VALUES ('serverpod', '20230522155355', 1, now()) 249 | ON CONFLICT ("module") 250 | DO UPDATE SET "version" = '20230522155355', "priority" = 1; 251 | 252 | 253 | COMMIT; 254 | -------------------------------------------------------------------------------- /slick_slides_server/migrations/serverpod/20230522155355/migration.sql: -------------------------------------------------------------------------------- 1 | BEGIN; 2 | 3 | -- 4 | -- ACTION CREATE TABLE 5 | -- 6 | CREATE TABLE "serverpod_auth_key" ( 7 | "id" serial PRIMARY KEY, 8 | "userId" integer NOT NULL, 9 | "hash" text NOT NULL, 10 | "scopeNames" json NOT NULL, 11 | "method" text NOT NULL 12 | ); 13 | 14 | -- Indexes 15 | CREATE INDEX "serverpod_auth_key_userId_idx" ON "serverpod_auth_key" USING btree ("userId"); 16 | 17 | -- 18 | -- ACTION CREATE TABLE 19 | -- 20 | CREATE TABLE "serverpod_cloud_storage" ( 21 | "id" serial PRIMARY KEY, 22 | "storageId" text NOT NULL, 23 | "path" text NOT NULL, 24 | "addedTime" timestamp without time zone NOT NULL, 25 | "expiration" timestamp without time zone, 26 | "byteData" bytea NOT NULL, 27 | "verified" boolean NOT NULL 28 | ); 29 | 30 | -- Indexes 31 | CREATE UNIQUE INDEX "serverpod_cloud_storage_path_idx" ON "serverpod_cloud_storage" USING btree ("storageId", "path"); 32 | CREATE INDEX "serverpod_cloud_storage_expiration" ON "serverpod_cloud_storage" USING btree ("expiration"); 33 | 34 | -- 35 | -- ACTION CREATE TABLE 36 | -- 37 | CREATE TABLE "serverpod_cloud_storage_direct_upload" ( 38 | "id" serial PRIMARY KEY, 39 | "storageId" text NOT NULL, 40 | "path" text NOT NULL, 41 | "expiration" timestamp without time zone NOT NULL, 42 | "authKey" text NOT NULL 43 | ); 44 | 45 | -- Indexes 46 | CREATE UNIQUE INDEX "serverpod_cloud_storage_direct_upload_storage_path" ON "serverpod_cloud_storage_direct_upload" USING btree ("storageId", "path"); 47 | 48 | -- 49 | -- ACTION CREATE TABLE 50 | -- 51 | CREATE TABLE "serverpod_future_call" ( 52 | "id" serial PRIMARY KEY, 53 | "name" text NOT NULL, 54 | "time" timestamp without time zone NOT NULL, 55 | "serializedObject" text, 56 | "serverId" text NOT NULL, 57 | "identifier" text 58 | ); 59 | 60 | -- Indexes 61 | CREATE INDEX "serverpod_future_call_time_idx" ON "serverpod_future_call" USING btree ("time"); 62 | CREATE INDEX "serverpod_future_call_serverId_idx" ON "serverpod_future_call" USING btree ("serverId"); 63 | CREATE INDEX "serverpod_future_call_identifier_idx" ON "serverpod_future_call" USING btree ("identifier"); 64 | 65 | -- 66 | -- ACTION CREATE TABLE 67 | -- 68 | CREATE TABLE "serverpod_health_connection_info" ( 69 | "id" serial PRIMARY KEY, 70 | "serverId" text NOT NULL, 71 | "timestamp" timestamp without time zone NOT NULL, 72 | "active" integer NOT NULL, 73 | "closing" integer NOT NULL, 74 | "idle" integer NOT NULL, 75 | "granularity" integer NOT NULL 76 | ); 77 | 78 | -- Indexes 79 | CREATE UNIQUE INDEX "serverpod_health_connection_info_timestamp_idx" ON "serverpod_health_connection_info" USING btree ("timestamp", "serverId", "granularity"); 80 | 81 | -- 82 | -- ACTION CREATE TABLE 83 | -- 84 | CREATE TABLE "serverpod_health_metric" ( 85 | "id" serial PRIMARY KEY, 86 | "name" text NOT NULL, 87 | "serverId" text NOT NULL, 88 | "timestamp" timestamp without time zone NOT NULL, 89 | "isHealthy" boolean NOT NULL, 90 | "value" double precision NOT NULL, 91 | "granularity" integer NOT NULL 92 | ); 93 | 94 | -- Indexes 95 | CREATE UNIQUE INDEX "serverpod_health_metric_timestamp_idx" ON "serverpod_health_metric" USING btree ("timestamp", "serverId", "name", "granularity"); 96 | 97 | -- 98 | -- ACTION CREATE TABLE 99 | -- 100 | CREATE TABLE "serverpod_method" ( 101 | "id" serial PRIMARY KEY, 102 | "endpoint" text NOT NULL, 103 | "method" text NOT NULL 104 | ); 105 | 106 | -- Indexes 107 | CREATE UNIQUE INDEX "serverpod_method_endpoint_method_idx" ON "serverpod_method" USING btree ("endpoint", "method"); 108 | 109 | -- 110 | -- ACTION CREATE TABLE 111 | -- 112 | CREATE TABLE "serverpod_readwrite_test" ( 113 | "id" serial PRIMARY KEY, 114 | "number" integer NOT NULL 115 | ); 116 | 117 | -- 118 | -- ACTION CREATE TABLE 119 | -- 120 | CREATE TABLE "serverpod_runtime_settings" ( 121 | "id" serial PRIMARY KEY, 122 | "logSettings" json NOT NULL, 123 | "logSettingsOverrides" json NOT NULL, 124 | "logServiceCalls" boolean NOT NULL, 125 | "logMalformedCalls" boolean NOT NULL 126 | ); 127 | 128 | -- 129 | -- ACTION CREATE TABLE 130 | -- 131 | CREATE TABLE "serverpod_session_log" ( 132 | "id" serial PRIMARY KEY, 133 | "serverId" text NOT NULL, 134 | "time" timestamp without time zone NOT NULL, 135 | "module" text, 136 | "endpoint" text, 137 | "method" text, 138 | "duration" double precision, 139 | "numQueries" integer, 140 | "slow" boolean, 141 | "error" text, 142 | "stackTrace" text, 143 | "authenticatedUserId" integer, 144 | "isOpen" boolean, 145 | "touched" timestamp without time zone NOT NULL 146 | ); 147 | 148 | -- Indexes 149 | CREATE INDEX "serverpod_session_log_serverid_idx" ON "serverpod_session_log" USING btree ("serverId"); 150 | CREATE INDEX "serverpod_session_log_touched_idx" ON "serverpod_session_log" USING btree ("touched"); 151 | CREATE INDEX "serverpod_session_log_isopen_idx" ON "serverpod_session_log" USING btree ("isOpen"); 152 | 153 | -- 154 | -- ACTION CREATE TABLE 155 | -- 156 | CREATE TABLE "serverpod_query_log" ( 157 | "id" serial PRIMARY KEY, 158 | "serverId" text NOT NULL, 159 | "sessionLogId" integer NOT NULL, 160 | "messageId" integer, 161 | "query" text NOT NULL, 162 | "duration" double precision NOT NULL, 163 | "numRows" integer, 164 | "error" text, 165 | "stackTrace" text, 166 | "slow" boolean NOT NULL, 167 | "order" integer NOT NULL 168 | ); 169 | 170 | -- Indexes 171 | CREATE INDEX "serverpod_query_log_sessionLogId_idx" ON "serverpod_query_log" USING btree ("sessionLogId"); 172 | 173 | -- Foreign keys 174 | ALTER TABLE ONLY "serverpod_query_log" 175 | ADD CONSTRAINT "serverpod_query_log_fk_0" 176 | FOREIGN KEY("sessionLogId") 177 | REFERENCES "serverpod_session_log"("id") 178 | ON DELETE CASCADE; 179 | 180 | -- 181 | -- ACTION CREATE TABLE 182 | -- 183 | CREATE TABLE "serverpod_message_log" ( 184 | "id" serial PRIMARY KEY, 185 | "sessionLogId" integer NOT NULL, 186 | "serverId" text NOT NULL, 187 | "messageId" integer NOT NULL, 188 | "endpoint" text NOT NULL, 189 | "messageName" text NOT NULL, 190 | "duration" double precision NOT NULL, 191 | "error" text, 192 | "stackTrace" text, 193 | "slow" boolean NOT NULL, 194 | "order" integer NOT NULL 195 | ); 196 | 197 | -- Foreign keys 198 | ALTER TABLE ONLY "serverpod_message_log" 199 | ADD CONSTRAINT "serverpod_message_log_fk_0" 200 | FOREIGN KEY("sessionLogId") 201 | REFERENCES "serverpod_session_log"("id") 202 | ON DELETE CASCADE; 203 | 204 | -- 205 | -- ACTION CREATE TABLE 206 | -- 207 | CREATE TABLE "serverpod_log" ( 208 | "id" serial PRIMARY KEY, 209 | "sessionLogId" integer NOT NULL, 210 | "messageId" integer, 211 | "reference" text, 212 | "serverId" text NOT NULL, 213 | "time" timestamp without time zone NOT NULL, 214 | "logLevel" integer NOT NULL, 215 | "message" text NOT NULL, 216 | "error" text, 217 | "stackTrace" text, 218 | "order" integer NOT NULL 219 | ); 220 | 221 | -- Indexes 222 | CREATE INDEX "serverpod_log_sessionLogId_idx" ON "serverpod_log" USING btree ("sessionLogId"); 223 | 224 | -- Foreign keys 225 | ALTER TABLE ONLY "serverpod_log" 226 | ADD CONSTRAINT "serverpod_log_fk_0" 227 | FOREIGN KEY("sessionLogId") 228 | REFERENCES "serverpod_session_log"("id") 229 | ON DELETE CASCADE; 230 | 231 | -- 232 | -- MIGRATION 1.1.0 233 | -- 234 | INSERT INTO "serverpod_migrations" ("module", "version", "priority", "timestamp") 235 | VALUES ('serverpod', '20230522155355', 1, now()) 236 | ON CONFLICT ("module") 237 | DO UPDATE SET "version" = '20230522155355', "priority" = 1; 238 | 239 | 240 | COMMIT; 241 | -------------------------------------------------------------------------------- /slick_slides_server/migrations/serverpod/20230529140912/definition.sql: -------------------------------------------------------------------------------- 1 | BEGIN; 2 | 3 | -- 4 | -- Class AuthKey as table serverpod_auth_key 5 | -- 6 | CREATE TABLE "serverpod_auth_key" ( 7 | "id" serial PRIMARY KEY, 8 | "userId" integer NOT NULL, 9 | "hash" text NOT NULL, 10 | "scopeNames" json NOT NULL, 11 | "method" text NOT NULL 12 | ); 13 | 14 | -- Indexes 15 | CREATE INDEX "serverpod_auth_key_userId_idx" ON "serverpod_auth_key" USING btree ("userId"); 16 | 17 | 18 | -- 19 | -- Class CloudStorageEntry as table serverpod_cloud_storage 20 | -- 21 | CREATE TABLE "serverpod_cloud_storage" ( 22 | "id" serial PRIMARY KEY, 23 | "storageId" text NOT NULL, 24 | "path" text NOT NULL, 25 | "addedTime" timestamp without time zone NOT NULL, 26 | "expiration" timestamp without time zone, 27 | "byteData" bytea NOT NULL, 28 | "verified" boolean NOT NULL 29 | ); 30 | 31 | -- Indexes 32 | CREATE UNIQUE INDEX "serverpod_cloud_storage_path_idx" ON "serverpod_cloud_storage" USING btree ("storageId", "path"); 33 | CREATE INDEX "serverpod_cloud_storage_expiration" ON "serverpod_cloud_storage" USING btree ("expiration"); 34 | 35 | 36 | -- 37 | -- Class CloudStorageDirectUploadEntry as table serverpod_cloud_storage_direct_upload 38 | -- 39 | CREATE TABLE "serverpod_cloud_storage_direct_upload" ( 40 | "id" serial PRIMARY KEY, 41 | "storageId" text NOT NULL, 42 | "path" text NOT NULL, 43 | "expiration" timestamp without time zone NOT NULL, 44 | "authKey" text NOT NULL 45 | ); 46 | 47 | -- Indexes 48 | CREATE UNIQUE INDEX "serverpod_cloud_storage_direct_upload_storage_path" ON "serverpod_cloud_storage_direct_upload" USING btree ("storageId", "path"); 49 | 50 | 51 | -- 52 | -- Class FutureCallEntry as table serverpod_future_call 53 | -- 54 | CREATE TABLE "serverpod_future_call" ( 55 | "id" serial PRIMARY KEY, 56 | "name" text NOT NULL, 57 | "time" timestamp without time zone NOT NULL, 58 | "serializedObject" text, 59 | "serverId" text NOT NULL, 60 | "identifier" text 61 | ); 62 | 63 | -- Indexes 64 | CREATE INDEX "serverpod_future_call_time_idx" ON "serverpod_future_call" USING btree ("time"); 65 | CREATE INDEX "serverpod_future_call_serverId_idx" ON "serverpod_future_call" USING btree ("serverId"); 66 | CREATE INDEX "serverpod_future_call_identifier_idx" ON "serverpod_future_call" USING btree ("identifier"); 67 | 68 | 69 | -- 70 | -- Class ServerHealthConnectionInfo as table serverpod_health_connection_info 71 | -- 72 | CREATE TABLE "serverpod_health_connection_info" ( 73 | "id" serial PRIMARY KEY, 74 | "serverId" text NOT NULL, 75 | "timestamp" timestamp without time zone NOT NULL, 76 | "active" integer NOT NULL, 77 | "closing" integer NOT NULL, 78 | "idle" integer NOT NULL, 79 | "granularity" integer NOT NULL 80 | ); 81 | 82 | -- Indexes 83 | CREATE UNIQUE INDEX "serverpod_health_connection_info_timestamp_idx" ON "serverpod_health_connection_info" USING btree ("timestamp", "serverId", "granularity"); 84 | 85 | 86 | -- 87 | -- Class ServerHealthMetric as table serverpod_health_metric 88 | -- 89 | CREATE TABLE "serverpod_health_metric" ( 90 | "id" serial PRIMARY KEY, 91 | "name" text NOT NULL, 92 | "serverId" text NOT NULL, 93 | "timestamp" timestamp without time zone NOT NULL, 94 | "isHealthy" boolean NOT NULL, 95 | "value" double precision NOT NULL, 96 | "granularity" integer NOT NULL 97 | ); 98 | 99 | -- Indexes 100 | CREATE UNIQUE INDEX "serverpod_health_metric_timestamp_idx" ON "serverpod_health_metric" USING btree ("timestamp", "serverId", "name", "granularity"); 101 | 102 | 103 | -- 104 | -- Class MethodInfo as table serverpod_method 105 | -- 106 | CREATE TABLE "serverpod_method" ( 107 | "id" serial PRIMARY KEY, 108 | "endpoint" text NOT NULL, 109 | "method" text NOT NULL 110 | ); 111 | 112 | -- Indexes 113 | CREATE UNIQUE INDEX "serverpod_method_endpoint_method_idx" ON "serverpod_method" USING btree ("endpoint", "method"); 114 | 115 | 116 | -- 117 | -- Class ReadWriteTestEntry as table serverpod_readwrite_test 118 | -- 119 | CREATE TABLE "serverpod_readwrite_test" ( 120 | "id" serial PRIMARY KEY, 121 | "number" integer NOT NULL 122 | ); 123 | 124 | 125 | -- 126 | -- Class RuntimeSettings as table serverpod_runtime_settings 127 | -- 128 | CREATE TABLE "serverpod_runtime_settings" ( 129 | "id" serial PRIMARY KEY, 130 | "logSettings" json NOT NULL, 131 | "logSettingsOverrides" json NOT NULL, 132 | "logServiceCalls" boolean NOT NULL, 133 | "logMalformedCalls" boolean NOT NULL 134 | ); 135 | 136 | 137 | -- 138 | -- Class SessionLogEntry as table serverpod_session_log 139 | -- 140 | CREATE TABLE "serverpod_session_log" ( 141 | "id" serial PRIMARY KEY, 142 | "serverId" text NOT NULL, 143 | "time" timestamp without time zone NOT NULL, 144 | "module" text, 145 | "endpoint" text, 146 | "method" text, 147 | "duration" double precision, 148 | "numQueries" integer, 149 | "slow" boolean, 150 | "error" text, 151 | "stackTrace" text, 152 | "authenticatedUserId" integer, 153 | "isOpen" boolean, 154 | "touched" timestamp without time zone NOT NULL 155 | ); 156 | 157 | -- Indexes 158 | CREATE INDEX "serverpod_session_log_serverid_idx" ON "serverpod_session_log" USING btree ("serverId"); 159 | CREATE INDEX "serverpod_session_log_touched_idx" ON "serverpod_session_log" USING btree ("touched"); 160 | CREATE INDEX "serverpod_session_log_isopen_idx" ON "serverpod_session_log" USING btree ("isOpen"); 161 | 162 | 163 | -- 164 | -- Class QueryLogEntry as table serverpod_query_log 165 | -- 166 | CREATE TABLE "serverpod_query_log" ( 167 | "id" serial PRIMARY KEY, 168 | "serverId" text NOT NULL, 169 | "sessionLogId" integer NOT NULL, 170 | "messageId" integer, 171 | "query" text NOT NULL, 172 | "duration" double precision NOT NULL, 173 | "numRows" integer, 174 | "error" text, 175 | "stackTrace" text, 176 | "slow" boolean NOT NULL, 177 | "order" integer NOT NULL 178 | ); 179 | 180 | -- Indexes 181 | CREATE INDEX "serverpod_query_log_sessionLogId_idx" ON "serverpod_query_log" USING btree ("sessionLogId"); 182 | 183 | -- Foreign keys 184 | ALTER TABLE ONLY "serverpod_query_log" 185 | ADD CONSTRAINT "serverpod_query_log_fk_0" 186 | FOREIGN KEY("sessionLogId") 187 | REFERENCES "serverpod_session_log"("id") 188 | ON DELETE CASCADE; 189 | 190 | 191 | -- 192 | -- Class MessageLogEntry as table serverpod_message_log 193 | -- 194 | CREATE TABLE "serverpod_message_log" ( 195 | "id" serial PRIMARY KEY, 196 | "sessionLogId" integer NOT NULL, 197 | "serverId" text NOT NULL, 198 | "messageId" integer NOT NULL, 199 | "endpoint" text NOT NULL, 200 | "messageName" text NOT NULL, 201 | "duration" double precision NOT NULL, 202 | "error" text, 203 | "stackTrace" text, 204 | "slow" boolean NOT NULL, 205 | "order" integer NOT NULL 206 | ); 207 | 208 | -- Foreign keys 209 | ALTER TABLE ONLY "serverpod_message_log" 210 | ADD CONSTRAINT "serverpod_message_log_fk_0" 211 | FOREIGN KEY("sessionLogId") 212 | REFERENCES "serverpod_session_log"("id") 213 | ON DELETE CASCADE; 214 | 215 | 216 | -- 217 | -- Class LogEntry as table serverpod_log 218 | -- 219 | CREATE TABLE "serverpod_log" ( 220 | "id" serial PRIMARY KEY, 221 | "sessionLogId" integer NOT NULL, 222 | "messageId" integer, 223 | "reference" text, 224 | "serverId" text NOT NULL, 225 | "time" timestamp without time zone NOT NULL, 226 | "logLevel" integer NOT NULL, 227 | "message" text NOT NULL, 228 | "error" text, 229 | "stackTrace" text, 230 | "order" integer NOT NULL 231 | ); 232 | 233 | -- Indexes 234 | CREATE INDEX "serverpod_log_sessionLogId_idx" ON "serverpod_log" USING btree ("sessionLogId"); 235 | 236 | -- Foreign keys 237 | ALTER TABLE ONLY "serverpod_log" 238 | ADD CONSTRAINT "serverpod_log_fk_0" 239 | FOREIGN KEY("sessionLogId") 240 | REFERENCES "serverpod_session_log"("id") 241 | ON DELETE CASCADE; 242 | 243 | 244 | -- 245 | -- MIGRATION 1.1.0 246 | -- 247 | INSERT INTO "serverpod_migrations" ("module", "version", "priority", "timestamp") 248 | VALUES ('serverpod', '20230529140912', 0, now()) 249 | ON CONFLICT ("module") 250 | DO UPDATE SET "version" = '20230529140912', "priority" = 0; 251 | 252 | 253 | COMMIT; 254 | -------------------------------------------------------------------------------- /slick_slides_server/migrations/serverpod/20230529140912/migration.sql: -------------------------------------------------------------------------------- 1 | BEGIN; 2 | 3 | -- 4 | -- ACTION CREATE TABLE 5 | -- 6 | CREATE TABLE "serverpod_auth_key" ( 7 | "id" serial PRIMARY KEY, 8 | "userId" integer NOT NULL, 9 | "hash" text NOT NULL, 10 | "scopeNames" json NOT NULL, 11 | "method" text NOT NULL 12 | ); 13 | 14 | -- Indexes 15 | CREATE INDEX "serverpod_auth_key_userId_idx" ON "serverpod_auth_key" USING btree ("userId"); 16 | 17 | -- 18 | -- ACTION CREATE TABLE 19 | -- 20 | CREATE TABLE "serverpod_cloud_storage" ( 21 | "id" serial PRIMARY KEY, 22 | "storageId" text NOT NULL, 23 | "path" text NOT NULL, 24 | "addedTime" timestamp without time zone NOT NULL, 25 | "expiration" timestamp without time zone, 26 | "byteData" bytea NOT NULL, 27 | "verified" boolean NOT NULL 28 | ); 29 | 30 | -- Indexes 31 | CREATE UNIQUE INDEX "serverpod_cloud_storage_path_idx" ON "serverpod_cloud_storage" USING btree ("storageId", "path"); 32 | CREATE INDEX "serverpod_cloud_storage_expiration" ON "serverpod_cloud_storage" USING btree ("expiration"); 33 | 34 | -- 35 | -- ACTION CREATE TABLE 36 | -- 37 | CREATE TABLE "serverpod_cloud_storage_direct_upload" ( 38 | "id" serial PRIMARY KEY, 39 | "storageId" text NOT NULL, 40 | "path" text NOT NULL, 41 | "expiration" timestamp without time zone NOT NULL, 42 | "authKey" text NOT NULL 43 | ); 44 | 45 | -- Indexes 46 | CREATE UNIQUE INDEX "serverpod_cloud_storage_direct_upload_storage_path" ON "serverpod_cloud_storage_direct_upload" USING btree ("storageId", "path"); 47 | 48 | -- 49 | -- ACTION CREATE TABLE 50 | -- 51 | CREATE TABLE "serverpod_future_call" ( 52 | "id" serial PRIMARY KEY, 53 | "name" text NOT NULL, 54 | "time" timestamp without time zone NOT NULL, 55 | "serializedObject" text, 56 | "serverId" text NOT NULL, 57 | "identifier" text 58 | ); 59 | 60 | -- Indexes 61 | CREATE INDEX "serverpod_future_call_time_idx" ON "serverpod_future_call" USING btree ("time"); 62 | CREATE INDEX "serverpod_future_call_serverId_idx" ON "serverpod_future_call" USING btree ("serverId"); 63 | CREATE INDEX "serverpod_future_call_identifier_idx" ON "serverpod_future_call" USING btree ("identifier"); 64 | 65 | -- 66 | -- ACTION CREATE TABLE 67 | -- 68 | CREATE TABLE "serverpod_health_connection_info" ( 69 | "id" serial PRIMARY KEY, 70 | "serverId" text NOT NULL, 71 | "timestamp" timestamp without time zone NOT NULL, 72 | "active" integer NOT NULL, 73 | "closing" integer NOT NULL, 74 | "idle" integer NOT NULL, 75 | "granularity" integer NOT NULL 76 | ); 77 | 78 | -- Indexes 79 | CREATE UNIQUE INDEX "serverpod_health_connection_info_timestamp_idx" ON "serverpod_health_connection_info" USING btree ("timestamp", "serverId", "granularity"); 80 | 81 | -- 82 | -- ACTION CREATE TABLE 83 | -- 84 | CREATE TABLE "serverpod_health_metric" ( 85 | "id" serial PRIMARY KEY, 86 | "name" text NOT NULL, 87 | "serverId" text NOT NULL, 88 | "timestamp" timestamp without time zone NOT NULL, 89 | "isHealthy" boolean NOT NULL, 90 | "value" double precision NOT NULL, 91 | "granularity" integer NOT NULL 92 | ); 93 | 94 | -- Indexes 95 | CREATE UNIQUE INDEX "serverpod_health_metric_timestamp_idx" ON "serverpod_health_metric" USING btree ("timestamp", "serverId", "name", "granularity"); 96 | 97 | -- 98 | -- ACTION CREATE TABLE 99 | -- 100 | CREATE TABLE "serverpod_method" ( 101 | "id" serial PRIMARY KEY, 102 | "endpoint" text NOT NULL, 103 | "method" text NOT NULL 104 | ); 105 | 106 | -- Indexes 107 | CREATE UNIQUE INDEX "serverpod_method_endpoint_method_idx" ON "serverpod_method" USING btree ("endpoint", "method"); 108 | 109 | -- 110 | -- ACTION CREATE TABLE 111 | -- 112 | CREATE TABLE "serverpod_readwrite_test" ( 113 | "id" serial PRIMARY KEY, 114 | "number" integer NOT NULL 115 | ); 116 | 117 | -- 118 | -- ACTION CREATE TABLE 119 | -- 120 | CREATE TABLE "serverpod_runtime_settings" ( 121 | "id" serial PRIMARY KEY, 122 | "logSettings" json NOT NULL, 123 | "logSettingsOverrides" json NOT NULL, 124 | "logServiceCalls" boolean NOT NULL, 125 | "logMalformedCalls" boolean NOT NULL 126 | ); 127 | 128 | -- 129 | -- ACTION CREATE TABLE 130 | -- 131 | CREATE TABLE "serverpod_session_log" ( 132 | "id" serial PRIMARY KEY, 133 | "serverId" text NOT NULL, 134 | "time" timestamp without time zone NOT NULL, 135 | "module" text, 136 | "endpoint" text, 137 | "method" text, 138 | "duration" double precision, 139 | "numQueries" integer, 140 | "slow" boolean, 141 | "error" text, 142 | "stackTrace" text, 143 | "authenticatedUserId" integer, 144 | "isOpen" boolean, 145 | "touched" timestamp without time zone NOT NULL 146 | ); 147 | 148 | -- Indexes 149 | CREATE INDEX "serverpod_session_log_serverid_idx" ON "serverpod_session_log" USING btree ("serverId"); 150 | CREATE INDEX "serverpod_session_log_touched_idx" ON "serverpod_session_log" USING btree ("touched"); 151 | CREATE INDEX "serverpod_session_log_isopen_idx" ON "serverpod_session_log" USING btree ("isOpen"); 152 | 153 | -- 154 | -- ACTION CREATE TABLE 155 | -- 156 | CREATE TABLE "serverpod_query_log" ( 157 | "id" serial PRIMARY KEY, 158 | "serverId" text NOT NULL, 159 | "sessionLogId" integer NOT NULL, 160 | "messageId" integer, 161 | "query" text NOT NULL, 162 | "duration" double precision NOT NULL, 163 | "numRows" integer, 164 | "error" text, 165 | "stackTrace" text, 166 | "slow" boolean NOT NULL, 167 | "order" integer NOT NULL 168 | ); 169 | 170 | -- Indexes 171 | CREATE INDEX "serverpod_query_log_sessionLogId_idx" ON "serverpod_query_log" USING btree ("sessionLogId"); 172 | 173 | -- Foreign keys 174 | ALTER TABLE ONLY "serverpod_query_log" 175 | ADD CONSTRAINT "serverpod_query_log_fk_0" 176 | FOREIGN KEY("sessionLogId") 177 | REFERENCES "serverpod_session_log"("id") 178 | ON DELETE CASCADE; 179 | 180 | -- 181 | -- ACTION CREATE TABLE 182 | -- 183 | CREATE TABLE "serverpod_message_log" ( 184 | "id" serial PRIMARY KEY, 185 | "sessionLogId" integer NOT NULL, 186 | "serverId" text NOT NULL, 187 | "messageId" integer NOT NULL, 188 | "endpoint" text NOT NULL, 189 | "messageName" text NOT NULL, 190 | "duration" double precision NOT NULL, 191 | "error" text, 192 | "stackTrace" text, 193 | "slow" boolean NOT NULL, 194 | "order" integer NOT NULL 195 | ); 196 | 197 | -- Foreign keys 198 | ALTER TABLE ONLY "serverpod_message_log" 199 | ADD CONSTRAINT "serverpod_message_log_fk_0" 200 | FOREIGN KEY("sessionLogId") 201 | REFERENCES "serverpod_session_log"("id") 202 | ON DELETE CASCADE; 203 | 204 | -- 205 | -- ACTION CREATE TABLE 206 | -- 207 | CREATE TABLE "serverpod_log" ( 208 | "id" serial PRIMARY KEY, 209 | "sessionLogId" integer NOT NULL, 210 | "messageId" integer, 211 | "reference" text, 212 | "serverId" text NOT NULL, 213 | "time" timestamp without time zone NOT NULL, 214 | "logLevel" integer NOT NULL, 215 | "message" text NOT NULL, 216 | "error" text, 217 | "stackTrace" text, 218 | "order" integer NOT NULL 219 | ); 220 | 221 | -- Indexes 222 | CREATE INDEX "serverpod_log_sessionLogId_idx" ON "serverpod_log" USING btree ("sessionLogId"); 223 | 224 | -- Foreign keys 225 | ALTER TABLE ONLY "serverpod_log" 226 | ADD CONSTRAINT "serverpod_log_fk_0" 227 | FOREIGN KEY("sessionLogId") 228 | REFERENCES "serverpod_session_log"("id") 229 | ON DELETE CASCADE; 230 | 231 | -- 232 | -- MIGRATION 1.1.0 233 | -- 234 | INSERT INTO "serverpod_migrations" ("module", "version", "priority", "timestamp") 235 | VALUES ('serverpod', '20230529140912', 0, now()) 236 | ON CONFLICT ("module") 237 | DO UPDATE SET "version" = '20230529140912', "priority" = 0; 238 | 239 | 240 | COMMIT; 241 | -------------------------------------------------------------------------------- /slick_slides_server/pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: slick_slides_server 2 | description: Starting point for a Serverpod server. 3 | # version: 1.0.0 4 | # homepage: https://www.example.com 5 | 6 | environment: 7 | sdk: '>=2.19.0 <4.0.0' 8 | 9 | dependencies: 10 | serverpod: 1.1.0 11 | 12 | dev_dependencies: 13 | lints: ^2.0.1 14 | -------------------------------------------------------------------------------- /slick_slides_server/web/static/css/style.css: -------------------------------------------------------------------------------- 1 | html { 2 | box-sizing: border-box; 3 | font-size: 14px; 4 | font-family: Arial, Helvetica, sans-serif; 5 | background: url('/images/background.svg') no-repeat center center fixed; 6 | -webkit-background-size: cover; 7 | -moz-background-size: cover; 8 | -o-background-size: cover; 9 | background-size: cover; 10 | } 11 | 12 | *, *:before, *:after { 13 | box-sizing: inherit; 14 | } 15 | 16 | body, h1, h2, h3, h4, h5, h6, p, ol, ul { 17 | margin: 0; 18 | padding: 0; 19 | font-weight: normal; 20 | } 21 | 22 | ol, ul { 23 | list-style: none; 24 | } 25 | 26 | img { 27 | max-width: 100%; 28 | height: auto; 29 | } 30 | 31 | body { 32 | padding: 16px; 33 | } 34 | 35 | hr { 36 | margin-top: 16px; margin-bottom: 16px; 37 | border: 0; 38 | height: 1px; 39 | background: #999; 40 | } 41 | 42 | .content { 43 | min-width: 300px; 44 | position: absolute; 45 | left: 50%; 46 | top: 50%; 47 | -webkit-transform: translate(-50%, -50%); 48 | transform: translate(-50%, -50%); 49 | background-color: white; 50 | border-radius: 8px; 51 | padding: 16px; 52 | box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.2), 0 6px 20px 0 rgba(0, 0, 0, 0.19); 53 | } 54 | 55 | .logo-box a { 56 | text-decoration: none; 57 | font-weight: bold; 58 | color: #666; 59 | } 60 | 61 | .logo-box { 62 | text-align: center; 63 | } 64 | 65 | .info-box p { 66 | margin-top: 2px; 67 | } 68 | 69 | .link-box { 70 | text-align: center; 71 | color: #999; 72 | } 73 | 74 | .link-box a { 75 | text-decoration: none; 76 | } -------------------------------------------------------------------------------- /slick_slides_server/web/static/images/background.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /slick_slides_server/web/templates/default.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Built with Serverpod 6 | 7 | 8 | 9 |
10 | 14 |
15 |
16 |

Served at: {{served}}

17 |

Run mode: {{runmode}}

18 |
19 |
20 | 27 |
28 | 29 | --------------------------------------------------------------------------------