@@ -21,6 +21,8 @@ tasks.register("templateCleanup") {
2121 it[0 ].sanitized() to it[1 ].sanitized()
2222 }
2323
24+ val nameCasePreserved = repository.split(" /" )[1 ].sanitizedPreservingCase()
25+
2426 file(path = " gradle/libs.versions.toml" ).replace(
2527 oldValue = " com.codermp.composeandroidtemplate" ,
2628 newValue = " com.$owner .$name "
@@ -31,7 +33,10 @@ tasks.register("templateCleanup") {
3133 )
3234
3335 changePackageName(owner = owner, name = name)
34- changeManifestFile(name = name)
36+ changeManifestFile(name = nameCasePreserved)
37+ changeAppClassFile(name = nameCasePreserved)
38+ changeThemeFile(name = nameCasePreserved)
39+ changeResourceFiles(name = nameCasePreserved)
3540
3641 // cleanup the cleanup :)
3742 file(path = " .github/workflows/cleanup.yml" ).delete()
@@ -43,18 +48,43 @@ tasks.register("templateCleanup") {
4348 }
4449}
4550
51+ /* *
52+ * [String] extension function that sanitizes a string by removing all non-alphanumeric characters and
53+ * converting it to lowercase.
54+ */
4655fun String.sanitized () = replace(
4756 regex = Regex (pattern = " [^A-Za-z0-9]" ),
4857 replacement = " "
4958).lowercase()
5059
60+ /* *
61+ * [String] extension function that sanitizes a string by removing all non-alphanumeric characters
62+ * while preserving the case. This is useful for cases where the original case of the string is
63+ * important, such as in class names.
64+ */
65+ fun String.sanitizedPreservingCase () = split(regex = Regex (" [^A-Za-z0-9]" ))
66+ .filter { it.isNotEmpty() }
67+ .joinToString(" " )
68+
69+ /* *
70+ * [File] extension function that replaces all occurrences of `oldValue` with `newValue` in the file.
71+ * @param oldValue The string to be replaced.
72+ * @param newValue The string to replace with.
73+ */
5174fun File.replace (oldValue : String , newValue : String ) {
5275 writeText(text = readText().replace(oldValue, newValue))
5376}
5477
55- fun srcDirectories () = projectDir.listFiles()!!
78+ /* *
79+ * Returns a list of source directories in the project.
80+ * It excludes the `buildSrc` directory to avoid unnecessary processing.
81+ */
82+ fun srcDirectories () = projectDir
83+ .listFiles()!!
5684 .filter { it.isDirectory && it.name != " buildSrc" }
57- .flatMap { it.listFiles()!! .filter { it.isDirectory && it.name == " src" } }
85+ .flatMap {
86+ it.listFiles()!! .filter { it.isDirectory && it.name == " src" }
87+ }
5888
5989@Suppress(" NestedBlockDepth" )
6090/* *
@@ -63,12 +93,18 @@ fun srcDirectories() = projectDir.listFiles()!!
6393 * @param name The name of the repository, usually the project name.
6494 */
6595fun changePackageName (owner : String , name : String ) {
66- srcDirectories().forEach {
67- it.walk().filter {
68- it.isFile && (it.extension == " kt" || it.extension == " kts" || it.extension == " xml" )
69- }.forEach {
70- it.replace(" com.codermp.composeandroidtemplate" , " com.$owner .$name " )
71- }
96+ srcDirectories().forEach { directory ->
97+ directory
98+ .walk()
99+ .filter {
100+ it.isFile && (it.extension == " kt" || it.extension == " kts" || it.extension == " xml" )
101+ }
102+ .forEach { file ->
103+ file.replace(
104+ oldValue = " com.codermp.composeandroidtemplate" ,
105+ newValue = " com.$owner .$name "
106+ )
107+ }
72108 }
73109 srcDirectories().forEach { srcDir ->
74110 srcDir
@@ -112,42 +148,100 @@ fun changePackageName(owner: String, name: String) {
112148 * @param name The name of the repository, usually the project name.
113149 */
114150fun changeManifestFile (name : String ) {
115- val capitalizedName = name.split(" -" , " _" )
116- .joinToString(" " ) { it.replaceFirstChar { char -> char.uppercaseChar() } }
117-
118- // Update AndroidManifest.xml files
119- projectDir.walk()
151+ // Update AndroidManifest.xml file
152+ projectDir
153+ .walk()
120154 .filter { it.name == " AndroidManifest.xml" }
121155 .forEach { manifestFile ->
122156 manifestFile.replace(
123157 oldValue = " android:name=\" .app.TemplateApp\" " ,
124- newValue = " android:name=\" .app.${capitalizedName} App\" "
158+ newValue = " android:name=\" .app.${name} App\" "
159+ )
160+ manifestFile.replace(
161+ oldValue = " android:theme=\" @style/Theme.ComposeAndroidTemplate.Starting\" " ,
162+ newValue = " android:theme=\" @style/Theme.$name .Starting\" " ,
125163 )
126164 }
165+ }
127166
128- // Update strings.xml files
129- projectDir.walk()
167+ /* *
168+ * Change the main application class file to reflect the new project name.
169+ * @param name The name of the repository, usually the project name.
170+ */
171+ fun changeAppClassFile (name : String ) {
172+ // Rename TemplateApp class file
173+ srcDirectories()
174+ .forEach { srcDir ->
175+ srcDir
176+ .walk()
177+ .filter { it.isFile && it.name == " TemplateApp.kt" }
178+ .forEach { templateAppFile ->
179+ // Update class name inside the file
180+ templateAppFile.replace(
181+ oldValue = " class TemplateApp" , newValue = " class ${name} App"
182+ )
183+ templateAppFile.replace(
184+ oldValue = " this@TemplateApp" , newValue = " this@${name} App"
185+ )
186+
187+ // Rename the file itself
188+ val newFile = File (templateAppFile.parent, " ${name} App.kt" )
189+ templateAppFile.renameTo(newFile)
190+ }
191+ }
192+ }
193+
194+ /* *
195+ * Change the Compose theme file to reflect the new project name.
196+ * @param name The name of the repository, usually the project name.
197+ */
198+ fun changeThemeFile (name : String ) {
199+ srcDirectories()
200+ .forEach { srcDir ->
201+ srcDir
202+ .walk()
203+ .filter { it.isFile && it.name == " Theme.kt" }
204+ .forEach { themeFile ->
205+ themeFile.replace(
206+ oldValue = " ComposeAndroidTemplateTheme" , newValue = " ${name} Theme"
207+ )
208+ }
209+ }
210+ }
211+
212+ /* *
213+ * Change the resource files such as themes.xml, strings.xml, and splash.xml.
214+ * @param name The name of the repository, usually the project name.
215+ */
216+ fun changeResourceFiles (name : String ) {
217+ // Update themes.xml file
218+ projectDir
219+ .walk()
220+ .filter { it.name == " themes.xml" }
221+ .forEach { themesFile ->
222+ themesFile.replace(
223+ oldValue = " Theme.ComposeAndroidTemplate" , newValue = " Theme.$name "
224+ )
225+ }
226+
227+ // Update strings.xml file
228+ projectDir
229+ .walk()
130230 .filter { it.name == " strings.xml" }
131231 .forEach { stringsFile ->
132232 stringsFile.replace(
133- oldValue = " Compose Android Template" ,
134- newValue = name.split(" -" , " _" )
135- .joinToString(" " ) { it.replaceFirstChar { char -> char.uppercaseChar() } }
233+ oldValue = " Compose Android Template" , newValue = name
136234 )
137235 }
138236
139- // Rename TemplateApp class files
140- srcDirectories().forEach { srcDir ->
141- srcDir.walk()
142- .filter { it.isFile && it.name == " TemplateApp.kt" }
143- .forEach { templateAppFile ->
144- // Update class name inside the file
145- templateAppFile.replace(" class TemplateApp" , " class ${capitalizedName} App" )
146- templateAppFile.replace(" this@TemplateApp" , " this@${capitalizedName} App" )
147-
148- // Rename the file itself
149- val newFile = File (templateAppFile.parent, " ${capitalizedName} App.kt" )
150- templateAppFile.renameTo(newFile)
151- }
152- }
237+ // Update splash.xml file
238+ projectDir
239+ .walk()
240+ .filter { it.name == " splash.xml" }
241+ .forEach { splashFile ->
242+ splashFile.replace(
243+ oldValue = " Theme.ComposeAndroidTemplate.Starting" ,
244+ newValue = " Theme.${name} .Starting"
245+ )
246+ }
153247}
0 commit comments