Skip to content

Commit

Permalink
Initial Commit
Browse files Browse the repository at this point in the history
  • Loading branch information
fasilwdr committed Jun 6, 2024
1 parent 5c00dc2 commit b77809c
Show file tree
Hide file tree
Showing 14 changed files with 654 additions and 1 deletion.
49 changes: 49 additions & 0 deletions .github/workflows/python-apk.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
name: Python and Flutter Build

on:
push:
branches:
- main

jobs:
build:
runs-on: ubuntu-latest

steps:
- name: Checkout code
uses: actions/checkout@v2

- name: Set up Python 3.12.1
uses: actions/setup-python@v2
with:
python-version: 3.12.1

- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install -r requierements.txt
- name: Set up Android SDK
uses: android-actions/setup-android@v2

- name: Set up Flutter
uses: subosito/flutter-action@v2
with:
flutter-version: '3.19.0' # La versión de Flutter que estás utilizando

- name: Build with Flet
run: |
flet build apk --product FletApp --project FletModel
- name: Create Release
uses: actions/upload-artifact@v2
with:
name: package
path: |
build/
dist/
bin/
lib/
include/
src/
if-no-files-found: error
118 changes: 117 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1 +1,117 @@
# Flet-Model

# Flet Model

This repository contains a simple Flet application demonstrating a basic structure and usage of the Flet framework.

## Repository Structure

```plaintext
Flet-Model/
├── assets
│ └── icon.png
├── core
│ └── base.py
├── views
│ └── main_view.py (Add add all flet views here)
├── main.py
└── manifest.json
```

### File Descriptions

- **assets/icon.png**: Placeholder for assets like icons and images.
- **core/base.py**: Contains the core classes and logic for the application.
- **views/main_view.py**: Example view demonstrating the usage of the `Model` and `Control` classes.
- **main.py**: Entry point for the Flet application, handling routing and initial setup.
- **manifest.json**: Configuration file specifying application metadata and views.

## Main Components

### main.py

This is the entry point of the application. It loads the configuration from `manifest.json`, dynamically imports the required modules, and sets up the routing and error handling.

### core/base.py

Defines the `Control` and `Model` classes which are used to represent UI components and views in the application.

- **Control**: Wrapper for Flet controls with additional properties.
- **Model**: Base class for creating views. It handles the creation and arrangement of `Control` instances.

### views/main_view.py

An example view demonstrating how to use the `Model` and `Control` classes.

```python
#main_view
import flet as ft
from core.base import Model, Control

class MainView(Model):
route = '/'

appbar = ft.AppBar(
leading=ft.Icon(ft.icons.PALETTE),
leading_width=40,
title=ft.Text("AppBar Example"),
center_title=False,
bgcolor=ft.colors.SURFACE_VARIANT,
actions=[
ft.IconButton(ft.icons.WB_SUNNY_OUTLINED),
ft.IconButton(ft.icons.FILTER_3),
ft.PopupMenuButton(
items=[
ft.PopupMenuItem(text="Item 1"),
]
),
],
)

name = Control(ft.TextField(label="Name"), sequence=1)
age = Control(ft.TextField(label="Age", keyboard_type=ft.KeyboardType.NUMBER), sequence=2)
submit_button = Control(ft.ElevatedButton(text="Submit", on_click="on_click_submit"), sequence=3)

def on_click_submit(self, e):
print("Submitted")
```

## Features
- can be use for string for assign action in Control class
-


## Usage

1. Clone the repository:
```bash
git clone https://github.com/fasilwdr/Flet-Model.git
cd Flet-Model
```
- Create views under views folder and map it into manifest.json
```json
{
"name": "Flet App",
"short_name": "Flet App",
"version": "1.0.1",
"views": [
"views/main_view.py",
"views/second_view.py"
]
}
```

2. Install the required dependencies:
```bash
pip install flet
```

3. Run the application:
```bash
flet main.py
```

The application should start, and you will see a simple form with fields for Name and Age, and a Submit button.

## License

This project is licensed under the MIT License.
Binary file added assets/icon.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/logo_128.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/logo_512.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 2 additions & 0 deletions core/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
from . import base
from . import controls
134 changes: 134 additions & 0 deletions core/base.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
import flet as ft


class Control:
"""
A class to represent a control in a Flet application.
Attributes:
flet_control: The actual Flet control instance.
visible (bool): Whether the control is visible.
overlay (bool): Whether the control is an overlay.
dialog (bool): Whether the control is a dialog.
sequence (int): The sequence number for ordering controls.
"""
def __init__(self, flet_control, visible: bool = True, overlay: bool = False, dialog: bool = False, sequence: int = 1):
self.flet_control = flet_control
self.visible = visible
self.overlay = overlay
self.dialog = dialog
self.sequence = sequence

def __getattr__(self, item):
# Delegate attribute access to the actual Flet control
return getattr(self.flet_control, item)

def __setattr__(self, key, value):
if key in ["flet_control", "visible", "overlay", "dialog", "sequence"]: # Avoid infinite recursion for internal attributes
super().__setattr__(key, value)
else:
setattr(self.flet_control, key, value)


class Model:
route = None
back_route = None
appbar = None
bottom_appbar = None
auto_scroll = None
bgcolor = None
drawer = None
end_drawer = None
fullscreen_dialog = False
floating_action_button = None
navigation_bar = None
horizontal_alignment = ft.CrossAxisAlignment.START
on_scroll_interval = 10
on_keyboard_event = None
padding = 10
scroll = None
on_scroll = None
spacing = 10
vertical_alignment = ft.MainAxisAlignment.START

def __init__(self, page):
self.page = page

def __post_init__(self):
self.post_init()

def on_view_pop(self, e):
self.page.go(self.back_route)

def init(self):
# self.bgcolor = ft.colors.PRIMARY
pass

def post_init(self):
pass

def create_view(self):
controls = []
# Collect all Control instances
control_instances = []
for attr_name in dir(self):
attr = getattr(self, attr_name)
if isinstance(attr, Control):
control_instances.append(attr)

# Sort the controls based on their sequence
sorted_controls = sorted(control_instances, key=lambda x: x.sequence)

# Add sorted controls to the view
for control in sorted_controls:
actual_flet_control = control.flet_control
for event in ['on_click', 'on_hover', 'on_long_press', 'on_change', 'on_dismiss']:
if hasattr(actual_flet_control, event):
callback_name = getattr(actual_flet_control, event)
if isinstance(callback_name, str):
method = getattr(self, callback_name, None)
if method:
setattr(actual_flet_control, event, method)
if control.visible and not control.overlay and not control.dialog:
controls.append(actual_flet_control)
if control.overlay:
self.page.overlay.append(actual_flet_control)
if control.dialog:
self.page.dialog = actual_flet_control
if self.appbar and self.back_route:
self.page.on_view_pop = self.on_view_pop
self.appbar.leading = ft.IconButton(icon=ft.icons.ARROW_BACK, on_click=lambda e: self.page.go(self.back_route))
if self.on_keyboard_event:
self.page.on_keyboard_event = None
self.page.on_keyboard_event = self.on_keyboard_event

self.init()
return ft.View(
route=self.route,
controls=controls,
appbar=self.appbar,
bottom_appbar=self.bottom_appbar,
auto_scroll=self.auto_scroll,
bgcolor=self.bgcolor,
drawer=self.drawer,
end_drawer=self.end_drawer,
fullscreen_dialog=self.fullscreen_dialog,
floating_action_button=self.floating_action_button,
horizontal_alignment=self.horizontal_alignment,
on_scroll_interval=self.on_scroll_interval,
padding=self.padding,
scroll=self.scroll,
spacing=self.spacing,
vertical_alignment=self.vertical_alignment,
navigation_bar=self.navigation_bar,
on_scroll=self.on_scroll
)


def view_model(page):
# Scan through subclasses of Model to find a matching route
for cls in Model.__subclasses__():
if cls.route == page.route:
return cls(page).create_view() # Pass the page object to the class
# If no matching class is found
raise ValueError("No view available for the given route")
53 changes: 53 additions & 0 deletions core/controls.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import flet as ft
from datetime import datetime, date


def UserError(page, text):
snackbar = ft.SnackBar(content=ft.Text(text, color=ft.colors.WHITE, text_align="center"), open=True, bgcolor=ft.colors.RED)
page.show_snack_bar(snackbar)


def UserInfo(page, text):
snackbar = ft.SnackBar(content=ft.Text(text, color=ft.colors.WHITE, text_align="center"), open=True, bgcolor=ft.colors.BLUE)
page.show_snack_bar(snackbar)


def UserWarning(page, text):
snackbar = ft.SnackBar(content=ft.Text(text, color=ft.colors.BLACK, text_align="center"), open=True, bgcolor=ft.colors.YELLOW)
page.show_snack_bar(snackbar)


def get_formated_date(date_string, format):
date_object = datetime.strptime(date_string, "%Y-%m-%dT%H:%M:%S.%f")
formatted_date = date_object.strftime(format)
return formatted_date


class DateField(ft.Container):
def __init__(self, label, value='', col=None, format='%d-%m-%Y'):
super().__init__()
self.value = value
self.format = format
self.date_picker = ft.DatePicker(
on_change=self.change_date,
current_date=datetime.strptime(self.value, '%d-%m-%Y').date() if self.value else None,
first_date=date(2023, 10, 1),
)
self.content = ft.Row(controls=[
ft.Text(label),
ft.IconButton(ft.icons.DATE_RANGE, on_click=self.pick_date),
ft.Text(self.value)
])
self.col = col
# self.border = ft.InputBorder.NONE
self.padding = 5
self.bgcolor = ft.colors.SURFACE

def pick_date(self, e):
self.page.overlay.append(self.date_picker)
self.page.update()
self.date_picker.pick_date()
def change_date(self, e):
self.value = get_formated_date(e.data, self.format)
self.content.controls[-1].value = self.value
self.content.controls[-1].update()
Loading

0 comments on commit b77809c

Please sign in to comment.