Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,7 @@
<h3>A Nextcloud app that lets you play Solitaire.</h3>
Want to play Solitaire? Go ahead! This is a tiny game generated on demand using just HTML5, CSS and JS.
</p>
Nextcloud Hub 10 (31.0.6) is compatible, the icons at the top may look funny, but the app does still work!
Nextcloud Hub 26 (34.0.0) is compatible, the icons at the top may look funny, but the app does still work!
June 10, 2026
Changed info.xml to increase the compatible version number of solitaire.
commented out allowevalscript which is no longer supported.
42 changes: 23 additions & 19 deletions appinfo/info.xml
Original file line number Diff line number Diff line change
@@ -1,28 +1,32 @@
<?xml version="1.0"?>
<info xmlns:xsi= "http://www.w3.org/2001/XMLSchema-instance"
<info xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="https://apps.nextcloud.com/schema/apps/info.xsd">
<id>solitaire</id>
<name>Solitaire</name>
<summary>Solitaire</summary>

<id>solitaire_emoji</id>
<name>Solitaire (Emoji Face Fork)</name>
<summary>Emoji‑Face Solitaire for Nextcloud</summary>

<description><![CDATA[
# Solitaire
A Nextcloud app that lets you play Solitaire.
A custom fork of the classic Nextcloud Solitaire app, redesigned to use
emoji‑style face suits (😀 😘 ☣️ 😈) instead of traditional card symbols.
This fork is optimized for Nextcloud 34+ and includes compatibility fixes,
cleaned‑up assets, and a simplified deck renderer.
]]></description>

<version>1.0.0</version>
<licence>public</licence>
<author mail="colin@derben.ca" homepage="https://derben.ca">DerBen</author>
<namespace>Solitaire</namespace>
<licence>agpl</licence>
<author>David</author>
<namespace>SolitaireEmoji</namespace>

<category>games</category>
<website>https://github.com/derbenx/nextcloud-solitaire</website>
<bugs>https://github.com/derbenx/nextcloud-solitaire/issues</bugs>
<screenshot>https://raw.githubusercontent.com/derbenx/nextcloud-solitaire/master/Solitaire.png</screenshot>

<website>https://github.com/scootercommuter-090/nextcloud-emoji-face-solitaire</website>
<bugs>https://github.com/scootercommuter-090/nextcloud-emoji-face-solitaire/issues</bugs>
<repository type="git">https://github.com/scootercommuter-090/nextcloud-emoji-face-solitaire.git</repository>

<dependencies>
<nextcloud min-version="25" max-version="30"/>
<nextcloud min-version="27" max-version="35" />
<php min-version="8.0" />
</dependencies>
<navigations>
<navigation>
<name>Solitaire</name>
<route>solitaire.page.index</route>
</navigation>
</navigations>

</info>
131 changes: 88 additions & 43 deletions js/cards.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,49 +19,94 @@ function dnm(canv,x,y,sz,nm,c){
ctx.font = sz+"px Arial";
ctx.fillText(Number.isInteger(nm) ? nm:nm.toUpperCase(), x-(sz/2), y+(sz/2));
}
function dsh(canv,x,y,sz,s){
var ctx = canv.getContext("2d");
if (s=='c' || s=='t') { c=1; }
if (s=='d' || s=='s') { c=2; }
if (s==1 || s=='c') {
//draw circle
ctx.beginPath();
ctx.arc(x, y,sz/2, 0, 2 * Math.PI);
ctx.fillStyle = c==1 ? "red" : 'black';
ctx.fill();
ctx.stroke();
}
if (s==2 || s=='s') {
//draw square
ctx.beginPath();
ctx.rect(x - (sz/2), y - (sz/2),sz,sz);
ctx.fillStyle = c==1 ? "red" : 'black';
ctx.fill();
ctx.stroke();
}
if (s==3 || s=='d') {
//draw diamond
ctx.beginPath();
ctx.moveTo(x, y-(sz/2));
ctx.lineTo(x - sz/2, y);
ctx.lineTo(x, y+(sz/2));
ctx.lineTo(x + sz/2, y);
ctx.closePath();
ctx.fillStyle = c==1 ? "red" : 'black';
ctx.fill();
ctx.stroke();
}
if (s==4 || s=='t') {
//draw triangle
ctx.beginPath();
ctx.moveTo(x, y-(sz/2));
ctx.lineTo(x-(sz/2), y+(sz/2));
ctx.lineTo(x+(sz/2), y+(sz/2));
ctx.closePath();
ctx.fillStyle = c==1 ? "red" : 'black';
ctx.fill();
ctx.stroke();
}

function dsh(canv, x, y, sz, s) {
const ctx = canv.getContext("2d");

// Colors
const yellow = "#F2D000";
const green = "#4AA000";
const outline = "#000000";

// Suit → face mapping
// c = hearts → smiley
// t = clubs → kissy
// s = spades → mr yuck
// d = diamonds → evil grin

let fill;
if (s === 'c' || s === 1) fill = yellow; // smiley
if (s === 't' || s === 4) fill = yellow; // kissy
if (s === 's' || s === 2) fill = green; // mr yuck
if (s === 'd' || s === 3) fill = green; // evil grin

ctx.lineWidth = 2;
ctx.strokeStyle = outline;
ctx.fillStyle = fill;

// Head radius
const r = Math.max(sz / 2.5, 6);

// Draw head
ctx.beginPath();
ctx.arc(x, y, r, 0, Math.PI * 2);
ctx.fill();
ctx.stroke();

// Pixel-ish unit
const u = Math.max(Math.floor(r / 4), 2);

// Eyes
ctx.fillStyle = outline;

// Left eye
ctx.fillRect(x - 2*u, y - u, u, u);

// Right eye
ctx.fillRect(x + u, y - u, u, u);

// Reset fill for mouths
ctx.fillStyle = outline;

// Mouths by suit
if (s === 'c' || s === 1) {
// 😀 Smiley
ctx.fillRect(x - 2*u, y + u, 4*u, u);
}

if (s === 't' || s === 4) {
// 😘 Kissy face (little puckered mouth)
ctx.fillRect(x - u/2, y + u, u, u);
}

if (s === 's' || s === 2) {
// Mr. Yuck (flat angry mouth)
ctx.fillRect(x - 2*u, y + u, 4*u, u);
ctx.fillRect(x - 2*u, y + u, u, u); // left fang
ctx.fillRect(x + u, y + u, u, u); // right fang
}

if (s === 'd' || s === 3) {
// Evil grin
ctx.fillRect(x - 2*u, y + u, 4*u, u);

// Left fang (triangle)
ctx.beginPath();
ctx.moveTo(x - 1.5*u, y + 2*u); // top-left
ctx.lineTo(x - 0.5*u, y + 2*u); // top-right
ctx.lineTo(x - u, y + 5*u); // bottom point
ctx.closePath();
ctx.fill();

// Right fang (triangle)
ctx.beginPath();
ctx.moveTo(x + 0.5*u, y + 2*u); // top-left
ctx.lineTo(x + 1.5*u, y + 2*u); // top-right
ctx.lineTo(x + u, y + 5*u); // bottom point
ctx.closePath();
ctx.fill();

}
}

function dcd(canv,x,y,c='',s=200,co1='lime',co2='green'){
Expand Down
4 changes: 2 additions & 2 deletions lib/Controller/PageController.php
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<?php
namespace OCA\Solitaire\Controller;
namespace OCA\SolitaireEmoji\Controller;

use OCP\IRequest;
use OCP\AppFramework\Http\TemplateResponse;
Expand Down Expand Up @@ -28,7 +28,7 @@ public function __construct($AppName, IRequest $request, $UserId){
public function index() {
$response = new TemplateResponse('solitaire', 'index'); // templates/index.php
$csp = new ContentSecurityPolicy();
$csp->allowEvalScript(true);
// $csp->allowEvalScript(true);
$response->setContentSecurityPolicy($csp);

return $response;
Expand Down