Skip to content

Commit f59bf14

Browse files
committed
* Add Adhkar Counter example
1 parent f3947e2 commit f59bf14

2 files changed

Lines changed: 261 additions & 0 deletions

File tree

examples/27_adhkar_counter.ring

Lines changed: 260 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,260 @@
1+
# Adhkar Counter App
2+
3+
load "webview.ring"
4+
load "jsonlib.ring"
5+
6+
oWebView = NULL
7+
nCount = 0
8+
nCurrentZikrIndex = 1
9+
10+
aAzkar = [
11+
["سُبْحَانَ اللَّهِ", 33],
12+
["الْحَمْدُ للّهِ", 33],
13+
["الْلَّهُ أَكْبَرُ", 34],
14+
["لَا إلَه إلّا اللهُ وَحْدَهُ لَا شَرِيكَ لَهُ، لَهُ الْمُلْكُ وَلَهُ الْحَمْدُ وَهُوَ عَلَى كُلُّ شَيْءِ قَدِيرِ", 1],
15+
]
16+
17+
18+
func main()
19+
oWebView = new WebView(1, NULL)
20+
21+
oWebView {
22+
setTitle("السبحة")
23+
setSize(500, 700, WEBVIEW_HINT_NONE)
24+
25+
bind("getInitialCount", :handleGetInitialCount)
26+
bind("incrementCounter", :handleIncrementCounter)
27+
bind("resetCounter", :handleResetCounter)
28+
29+
loadSebhaHTML()
30+
31+
run()
32+
}
33+
34+
func loadSebhaHTML()
35+
cHTML = `
36+
<!DOCTYPE html>
37+
<html dir="rtl" lang="ar">
38+
<head>
39+
<meta charset="UTF-8">
40+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
41+
<!-- Font Awesome for icons -->
42+
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.1/css/all.min.css">
43+
<style>
44+
@import url('https://fonts.googleapis.com/css2?family=Tajawal:wght@400;700&display=swap');
45+
:root {
46+
--bg-color: #000000;
47+
--card-bg: rgba(30, 30, 32, 0.6);
48+
--border-color: rgba(255, 255, 255, 0.1);
49+
--text-primary: #f8fafc;
50+
--text-secondary: #a1a1aa;
51+
--accent-green: #4ade80;
52+
--accent-red: #f87171;
53+
}
54+
body {
55+
font-family: 'Tajawal', sans-serif;
56+
display: flex;
57+
flex-direction: column;
58+
justify-content: center;
59+
align-items: center;
60+
height: 100vh;
61+
margin: 0;
62+
background-color: var(--bg-color);
63+
user-select: none;
64+
position: relative;
65+
overflow: hidden;
66+
color: var(--text-primary);
67+
}
68+
.background-container {
69+
position: fixed; top: 0; left: 0; width: 100%; height: 100%;
70+
z-index: -1; overflow: hidden;
71+
}
72+
.aurora {
73+
position: relative; width: 100%; height: 100%;
74+
filter: blur(150px); opacity: 0.5;
75+
}
76+
.aurora-shape1 {
77+
position: absolute; width: 50vw; height: 50vh;
78+
background: radial-gradient(circle, #22d3ee, transparent 60%);
79+
top: 5%; left: 5%;
80+
}
81+
.aurora-shape2 {
82+
position: absolute; width: 40vw; height: 40vh;
83+
background: radial-gradient(circle, #c084fc, transparent 60%);
84+
bottom: 10%; right: 10%;
85+
}
86+
87+
.sebha-container {
88+
text-align: center;
89+
background-color: var(--card-bg);
90+
padding: 2em;
91+
border-radius: 15px;
92+
box-shadow: 0 8px 30px rgba(0,0,0,0.3);
93+
backdrop-filter: blur(12px);
94+
-webkit-backdrop-filter: blur(12px);
95+
border: 1px solid var(--border-color);
96+
position: relative; z-index: 1;
97+
width: 90%;
98+
max-width: 400px;
99+
}
100+
h1 {
101+
font-size: 1.8em;
102+
color: var(--text-primary);
103+
margin-bottom: 1em;
104+
}
105+
.counter-display {
106+
background-color: rgba(255, 255, 255, 0.05);
107+
width: 100%;
108+
height: 120px;
109+
line-height: 120px;
110+
border-radius: 15px;
111+
box-shadow: inset 0 2px 5px rgba(0,0,0,0.2);
112+
font-size: 4em;
113+
font-weight: 700;
114+
color: var(--accent-green);
115+
margin-bottom: 30px;
116+
border: 1px solid var(--border-color);
117+
}
118+
.tasbih-button {
119+
width: 180px;
120+
height: 180px;
121+
border-radius: 50%;
122+
border: none;
123+
background-color: var(--accent-green);
124+
color: white;
125+
font-size: 2em;
126+
font-weight: 700;
127+
cursor: pointer;
128+
box-shadow: 0 5px 15px rgba(0, 128, 0, 0.4);
129+
transition: transform 0.1s, box-shadow 0.1s, background-color 0.2s;
130+
display: flex;
131+
align-items: center;
132+
justify-content: center;
133+
margin: 0 auto 30px auto;
134+
}
135+
.tasbih-button:active {
136+
transform: scale(0.95);
137+
box-shadow: 0 2px 8px rgba(0, 128, 0, 0.5);
138+
}
139+
.tasbih-button:hover {
140+
background-color: #00a884;
141+
}
142+
.reset-button {
143+
background: none;
144+
border: 1px solid var(--accent-red);
145+
color: var(--accent-red);
146+
padding: 0.8em 2em;
147+
border-radius: 10px;
148+
cursor: pointer;
149+
font-size: 1.1em;
150+
font-weight: 500;
151+
transition: all 0.2s ease;
152+
}
153+
.reset-button:hover {
154+
background-color: var(--accent-red);
155+
color: white;
156+
box-shadow: 0 4px 10px rgba(0,0,0,0.2);
157+
}
158+
@media (max-width: 480px) {
159+
.sebha-container {
160+
padding: 1.5em;
161+
}
162+
.counter-display {
163+
font-size: 3em;
164+
height: 100px;
165+
line-height: 100px;
166+
}
167+
.tasbih-button {
168+
width: 150px;
169+
height: 150px;
170+
font-size: 1.8em;
171+
}
172+
.reset-button {
173+
font-size: 1em;
174+
padding: 0.7em 1.5em;
175+
}
176+
}
177+
</style>
178+
</head>
179+
<body>
180+
<div class="background-container">
181+
<div class="aurora"><div class="aurora-shape1"></div><div class="aurora-shape2"></div></div>
182+
</div>
183+
<div class="sebha-container">
184+
<h1><i class="fa-solid fa-mosque"></i> السبحة</h1>
185+
<div id="zikr-text" style="font-size: 1.5em; margin-bottom: 15px; color: var(--text-primary);"></div>
186+
<div id="counter" class="counter-display">0</div>
187+
<button id="tasbih-btn" class="tasbih-button">سبّح</button>
188+
<button id="reset-btn" class="reset-button">تصفير</button>
189+
</div>
190+
191+
<script>
192+
function updateCounter(count, zikrText) {
193+
document.getElementById('counter').textContent = count;
194+
document.getElementById('zikr-text').textContent = zikrText;
195+
}
196+
197+
async function increment() {
198+
// We don't need to wait for a response if we update the UI from Ring
199+
window.incrementCounter();
200+
}
201+
202+
async function reset() {
203+
if (confirm('هل أنت متأكد أنك تريد تصفير العداد؟')) {
204+
window.resetCounter();
205+
}
206+
}
207+
208+
window.onload = async () => {
209+
try {
210+
const initialData = await window.getInitialCount();
211+
updateCounter(initialData.count, initialData.zikr);
212+
} catch (e) { console.error('Error getting initial count:', e); }
213+
214+
document.getElementById('tasbih-btn').addEventListener('click', increment);
215+
document.getElementById('reset-btn').addEventListener('click', reset);
216+
};
217+
</script>
218+
</body>
219+
</html>
220+
`
221+
oWebView.setHtml(cHTML)
222+
223+
224+
# Handles requests from JavaScript to get the initial counter value and current Zikr text.
225+
func handleGetInitialCount(id, req)
226+
see "Ring: JavaScript requests initial counter value and Zikr text." + nl
227+
aResponse = [
228+
:count = nCount,
229+
:zikr = aAzkar[nCurrentZikrIndex][1]
230+
]
231+
oWebView.wreturn(id, WEBVIEW_ERROR_OK, list2json(aResponse))
232+
233+
# Handles requests from JavaScript to increment the counter.
234+
func handleIncrementCounter(id, req)
235+
nCount++
236+
see "Ring: Counter incremented to: " + nCount + nl
237+
238+
if nCount >= aAzkar[nCurrentZikrIndex][2]
239+
nCurrentZikrIndex++
240+
nCount = 0
241+
if nCurrentZikrIndex > len(aAzkar)
242+
nCurrentZikrIndex = 1
243+
ok
244+
see "Ring: Switched to next Zikr: " + aAzkar[nCurrentZikrIndex][1] + nl
245+
ok
246+
247+
updateUICounter()
248+
oWebView.wreturn(id, WEBVIEW_ERROR_OK, '{}')
249+
250+
# Handles requests from JavaScript to reset the counter.
251+
func handleResetCounter(id, req)
252+
nCount = 0
253+
see "Ring: Counter has been reset." + nl
254+
updateUICounter()
255+
oWebView.wreturn(id, WEBVIEW_ERROR_OK, '{}')
256+
257+
# Updates the counter and Zikr text displayed in the WebView UI.
258+
func updateUICounter()
259+
cJsCode = "updateCounter(" + nCount + ", '" + aAzkar[nCurrentZikrIndex][1] + "');"
260+
oWebView.evalJS(cJsCode)

package.ring

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ aPackageInfo = [
5656
"examples/24_ringfetch.ring",
5757
"examples/25_drawing.ring",
5858
"examples/26_using_weblib.ring",
59+
"examples/27_adhkar_counter.ring",
5960
"README.md",
6061
"docs/REFERENCE.md",
6162
"docs/USAGE.md",

0 commit comments

Comments
 (0)