Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
dbb9e3428d |
@@ -1,5 +1,11 @@
|
||||
# Sanctuary
|
||||
|
||||
## beta.165 — article Gazette et conversation
|
||||
|
||||
Grande photo et texte dans un même conteneur à gauche, auteur dessous, réponses
|
||||
à droite ou sous l’article sur petit écran.
|
||||
[Résultat et vérifications](docs/gazette-scene-beta165.md).
|
||||
|
||||
## beta.164 — calendrier et intendance
|
||||
|
||||
Date et heure réunies à gauche ; titre serveur aligné sur la carte et les panneaux.
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
# beta.165 — Gazette en article et conversation
|
||||
|
||||
Photo en tête, titre et description dessous dans le même conteneur sombre.
|
||||
Auteur, visage, date et actions sous le conteneur. Réponses à droite avec
|
||||
défilement indépendant et saisie fixe ; sur GUI étroit, réponses sous l’article.
|
||||
Retour et Actualiser restent en haut, comme pour le tableau.
|
||||
|
||||
Interface cliente uniquement, sans changement de stockage ni de monde.
|
||||
Test client Vulkan réussi en FR/EN aux échelles GUI 2, 3 et 4 :
|
||||
position du panneau de réponses, repli sous l’article, défilement disponible,
|
||||
brouillon conservé après redimensionnement et réponse envoyée puis relue.
|
||||
Le scénario existant du tableau et celui du menu pause passent également.
|
||||
Captures conservées dans `build/qa-beta165/` (image synthétique de test).
|
||||
Inspection visuelle FR GUI 2 et GUI 4 effectuée.
|
||||
Journal : `build/beta165-client.log`.
|
||||
|
||||
`check build assemblePack --continue` exécuté : mêmes 23 GameTests en échec
|
||||
qu’en beta.164, aucun nouvel échec. Comparaison enregistrée dans
|
||||
`build/session165-server-failures.json`. La vérification générale reste en échec.
|
||||
Assemblage séparé réussi avec `build assemblePack :sanctuary-test:exportDuoLaunch
|
||||
-x :sanctuary:check` après cette vérification.
|
||||
|
||||
JAR local : `mods/sanctuary/build/libs/sanctuary-beta.165.jar`.
|
||||
SHA-256 : `03a954caf68089862b1d237dcf1ebaa501e3ce3cfedb1f5184e9412e73fd711d`.
|
||||
Anciens JAR conservés ; aucune publication distante.
|
||||
|
||||
+2
-2
@@ -9,8 +9,8 @@ loom_version=1.17.20
|
||||
fabric_api_version=0.160.5+26.3
|
||||
|
||||
# Release counter: beta.001, .002, .003, ... (see docs/versioning.md).
|
||||
mod_version=beta.164
|
||||
pack_version=beta.164
|
||||
mod_version=beta.165
|
||||
pack_version=beta.165
|
||||
resource_pack_version=beta.121
|
||||
maven_group=fr.koka.sanctuary
|
||||
jei_version=30.32.0-sanctuary.3
|
||||
|
||||
+24
@@ -95,6 +95,7 @@ public final class Community158ClientChecks implements FabricClientGameTest {
|
||||
c.runOnClient(m->{check(button(m.gui.screen(),"publish").active,"Photo enables publishing");check(edit(m.gui.screen()).getValue().equals("Une journée au village"),"Selection retains draft");press(m.gui.screen(),"sanctuary.community.publish");});
|
||||
c.waitFor(m->has(m.gui.screen(),"sanctuary.community.reply")&&!CommunityClient.pending(),600);
|
||||
c.runOnClient(m->{var article=widgets(m.gui.screen()).filter(CommunityArticle.class::isInstance).map(CommunityArticle.class::cast).findFirst().orElseThrow();var face=widgets(m.gui.screen()).filter(PlayerFaceWidget.class::isInstance).map(PlayerFaceWidget.class::cast).findFirst().orElseThrow();check(face.getY()>=article.getBottom(),"Author metadata below the article");check(button(m.gui.screen(),"actions").getY()==face.getY(),"Author metadata next to ellipsis");check(widgets(m.gui.screen()).anyMatch(w->w instanceof AbstractWidget widget && widget.getMessage().getString().contains("/"+java.time.Year.now()+" ")),"Article date includes year");});
|
||||
articleSceneChecks(c);
|
||||
c.takeScreenshot("cards158-article"+(database?"-database":"-file"));
|
||||
world.getServer().runOnServer(s->{try {
|
||||
var config=CommunityConfig.load(net.fabricmc.loader.api.FabricLoader.getInstance().getConfigDir().resolve("sanctuary-community.json"));
|
||||
@@ -224,6 +225,29 @@ public final class Community158ClientChecks implements FabricClientGameTest {
|
||||
System.out.println("SEARCH159_CLIENT_PASS mode="+(database?"database":"file"));
|
||||
} finally {intro.set(false);}
|
||||
}
|
||||
private static void articleSceneChecks(ClientGameTestContext c) {
|
||||
for(String locale:List.of("fr_fr","en_us"))for(int scale:List.of(2,3,4)) {
|
||||
c.runOnClient(m->{m.getLanguageManager().setSelected(locale);m.getLanguageManager().onResourceManagerReload(m.getResourceManager());m.options.guiScale().set(scale);m.resizeGui();});
|
||||
c.waitTicks(3);
|
||||
c.runOnClient(m->{
|
||||
var s=m.gui.screen();var article=widgets(s).filter(CommunityArticle.class::isInstance).map(CommunityArticle.class::cast).findFirst().orElseThrow();
|
||||
check(button(s,"back").getBottom()<=article.getY(),"Gazette toolbar fixed above article");
|
||||
if(s.width>=522) {
|
||||
check(body(s).getX()>=article.getRight(),"Gazette conversation on the right");
|
||||
check(button(s,"reply").getBottom()<=s.height-33,"Gazette composer above footer");
|
||||
} else {
|
||||
check(body(s).getY()>article.getBottom(),"Narrow Gazette stacks conversation below article");
|
||||
check(widgets(s).filter(AbstractScrollArea.class::isInstance).map(AbstractScrollArea.class::cast).anyMatch(a->a.maxScrollAmount()>0),"Narrow article and conversation scroll");
|
||||
}
|
||||
body(s).setValue("Brouillon Gazette165");
|
||||
});
|
||||
c.takeScreenshot("gazette165-article-"+locale+"-"+scale);
|
||||
}
|
||||
c.runOnClient(m->{m.options.guiScale().set(2);m.resizeGui();check(body(m.gui.screen()).getValue().equals("Brouillon Gazette165"),"Gazette draft survives resize");body(m.gui.screen()).setValue("Réponse Gazette165");press(m.gui.screen(),"sanctuary.community.reply");});
|
||||
c.waitFor(m->!CommunityClient.pending()&&widgets(m.gui.screen()).filter(CommunityBubble.class::isInstance).map(CommunityBubble.class::cast).anyMatch(w->w.getMessage().getString().equals("Réponse Gazette165")),300);
|
||||
c.takeScreenshot("gazette165-conversation");
|
||||
System.out.println("GAZETTE165_SCENE_PASS");
|
||||
}
|
||||
private static void noticeSceneChecks(ClientGameTestContext c) {
|
||||
for(String locale:List.of("fr_fr","en_us"))for(int scale:List.of(2,3,4)) {
|
||||
c.runOnClient(m->{m.getLanguageManager().setSelected(locale);m.getLanguageManager().onResourceManagerReload(m.getResourceManager());m.options.guiScale().set(scale);m.resizeGui();});
|
||||
|
||||
@@ -8,30 +8,27 @@ import net.minecraft.client.gui.components.*;
|
||||
import net.minecraft.client.gui.narration.NarrationElementOutput;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.util.FormattedCharSequence;
|
||||
import net.minecraft.world.item.component.ResolvableProfile;
|
||||
import static fr.koka.sanctuary.client.CommunityClient.*;
|
||||
|
||||
/** Photo left, generous headline and smaller text right, followed by the separate discussion. */
|
||||
/** Full-width hero photo, headline and description share one dark article container. */
|
||||
final class CommunityArticle extends AbstractWidget implements AutoCloseable {
|
||||
private final JsonObject entry;
|
||||
private final int imageWidth,textX;
|
||||
private final int imageWidth,imageHeight;
|
||||
private final float titleScale=1.35f;
|
||||
private final List<FormattedCharSequence> title,body;
|
||||
private CommunityPhotoWidget photo;
|
||||
CommunityArticle(int width,JsonObject entry) {
|
||||
super(0,0,width,100,Component.literal(str(entry,"title")));this.entry=entry;imageWidth=Math.max(72,width*42/100-16);textX=imageWidth+24;
|
||||
super(0,0,width,100,Component.literal(str(entry,"title")));imageWidth=width-20;imageHeight=Math.max(40,imageWidth*9/16);
|
||||
var font=Minecraft.getInstance().font;
|
||||
title=font.split(getMessage().copy().withStyle(net.minecraft.ChatFormatting.BOLD),Math.max(30,(int)((width-textX-12)/titleScale)));
|
||||
body=font.split(Component.literal(str(entry,"body")),Math.max(40,width-textX-12));
|
||||
height=Math.max(imageWidth*9/16+24,24+title.size()*15+12+body.size()*11);
|
||||
title=font.split(getMessage().copy().withStyle(net.minecraft.ChatFormatting.BOLD),Math.max(30,(int)((width-24)/titleScale)));
|
||||
body=font.split(Component.literal(str(entry,"body")),Math.max(40,width-24));
|
||||
height=12+imageHeight+14+title.size()*15+10+body.size()*11+12;
|
||||
try {
|
||||
if(!str(entry,"photo").isEmpty())photo=new CommunityPhotoWidget(imageWidth,Math.max(40,imageWidth*9/16),fr.koka.sanctuary.community.CommunityPhoto.decode(Base64.getDecoder().decode(str(entry,"photo")),960,540),text("photo"),false,null);
|
||||
if(!str(entry,"photo").isEmpty())photo=new CommunityPhotoWidget(imageWidth,imageHeight,fr.koka.sanctuary.community.CommunityPhoto.decode(Base64.getDecoder().decode(str(entry,"photo")),960,540),text("photo"),false,null);
|
||||
}catch(Exception ignored){}
|
||||
active=false;
|
||||
}
|
||||
int textOffset(){return textX;}
|
||||
@Override protected void extractWidgetRenderState(GuiGraphicsExtractor g,int mx,int my,float delta) {
|
||||
var font=Minecraft.getInstance().font;int x=getX(),y=getY(),tx=x+textX,top=y+12;
|
||||
var font=Minecraft.getInstance().font;int x=getX(),y=getY(),tx=x+12,top=y+12+imageHeight+14;
|
||||
g.fill(x,y,getRight(),getBottom(),0xed171d23);
|
||||
if(photo!=null){photo.setPosition(x+10,y+12);photo.extractRenderState(g,mx,my,delta);}
|
||||
else g.text(font,text("photo_unavailable"),x+10,y+12,0xffaaaaaa,false);
|
||||
|
||||
@@ -55,7 +55,7 @@ public final class CommunityScreen extends BlocodexFrame {
|
||||
@Override protected void init() {
|
||||
searchBox=null;
|
||||
closePhotos();initFrame("history",text(kind)); contentX=(width-contentWidth)/2; int w = contentWidth - 28;
|
||||
if(!composing && kind.equals("notice") && data.has("thread")) {noticeDetail(data.getAsJsonObject("thread"),w);return;}
|
||||
if(!composing && (kind.equals("notice") || kind.equals("article")) && data.has("thread")) {communityDetail(data.getAsJsonObject("thread"),w);return;}
|
||||
var layout = LinearLayout.vertical().spacing(8);
|
||||
if (!message.isEmpty()) line(layout,w,text(message));
|
||||
if (!available()) line(layout,w,text("unavailable"));
|
||||
@@ -120,7 +120,7 @@ public final class CommunityScreen extends BlocodexFrame {
|
||||
DRAFTS.values().removeIf(value->value==replyDraft);message="saved";needsLoad=true;stale=true;
|
||||
}));
|
||||
}
|
||||
private void noticeDetail(JsonObject thread,int w) {
|
||||
private void communityDetail(JsonObject thread,int w) {
|
||||
var entry=thread.getAsJsonObject("entry");
|
||||
var toolbar=LinearLayout.horizontal().spacing(5);
|
||||
button(toolbar,90,"back",()->{id="";page=0;data=new JsonObject();needsLoad=true;rebuildWidgets();});
|
||||
@@ -132,10 +132,15 @@ public final class CommunityScreen extends BlocodexFrame {
|
||||
var scene=LinearLayout.vertical().spacing(8);
|
||||
if(!message.isEmpty())line(scene,leftWidth,text(message));
|
||||
if(!available())line(scene,leftWidth,text("unavailable"));
|
||||
scene.addChild(new CommunityNoticeScene(leftWidth,entry));
|
||||
author(scene,leftWidth,entry,true);
|
||||
if(kind.equals("article")) {
|
||||
var article=new CommunityArticle(leftWidth,entry);cards.add(article);scene.addChild(article);
|
||||
articleAuthor(scene,leftWidth,entry);
|
||||
} else {
|
||||
scene.addChild(new CommunityNoticeScene(leftWidth,entry));
|
||||
author(scene,leftWidth,entry,true);
|
||||
}
|
||||
if(expandedId.equals(id))controls(scene,leftWidth,entry);
|
||||
taskDetails(scene,leftWidth,entry);
|
||||
if(kind.equals("notice"))taskDetails(scene,leftWidth,entry);
|
||||
if(columns) {
|
||||
scrollColumn(scene,leftWidth,contentX+8,top,availableHeight);
|
||||
int rightWidth=w-leftWidth-20,rightX=contentX+8+leftWidth+20;
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
name = "Sanctuary"
|
||||
author = "KOKA99CAB"
|
||||
version = "beta.164"
|
||||
version = "beta.165"
|
||||
pack-format = "packwiz:1.1.0"
|
||||
|
||||
[index]
|
||||
|
||||
Reference in New Issue
Block a user